How to write a generic factory method in swift?

I'm not sure how, if possible, to write a method that calls the constructor of its general type, inheriting from the common well-known base class <T: Base>, to create some instances of T without resorting to the explicit factory function, i.e. With all calls and whistles provided by type of output.

An example that works in a playground:

// Let there be classes MyPod and Boomstick with common Base (not important)
class Base : Printable {
    let value : String; init(_ value : String) { self.value = "Base." + value }
    var description: String { return value }
}
class MyPod : Base {
    init(_ value: String) { super.init("MyPod." + value) }
}
class Boomstick : Base {
    init(_ value: String) { super.init("Boomstick." + value) }
}
// PROBLEM: do not know how to force call of Boomstick(n) instead of Base(n) in here
func createSome<T : Base>() -> T[] {
    var result = Array<T>()
    for n in 1...5 {
        result += T(toString(n))
    }
    return result
}
// This seems to be fine. 
// I was expecting call of createSome<Boomstick>() { ... result += Boomstick(n) ...
let objs : Boomstick[] = createSome() 
// Prints: Base.1, Base.2, ... not much wished Boomstick.1, Boomstick.2, ...
println(objs)

One obvious solution is to delegate the creation to the caller, but this seems awkward:

func createSome<T>(factory : (Int)->T) { ... }

Thank.

PS: Isn't createSome () β†’ Base [] assigned to violate security rules like Boomstick []?

+4
source share
1 answer

, , , , :

protocol A {
    init(_ value: String)
}

,

class Base : Printable, A {
    let value : String;
    init(_ value : String) { self.value = "Base." + value }
    var description: String { return value }
}

class MyPod : Base, A {
    init(_ value: String) { super.init("MyPod." + value) }
}

class Boomstick : Base, A {
    init(_ value: String) { super.init("Boomstick." + value) }
}

A, Base createSome() func

func createSome<T : A>() -> [T] {
    var result = Array<T>()
    for n in 1...5 {
        result += T(toString(n))
    }
    return result
}

:

let objs : [Boomstick] = createSome()
objs[0]

:

{value "Base.Boomstick.1"}

MyPod Base, . , .

+4

Source: https://habr.com/ru/post/1545473/


All Articles