【问题标题】:How to write generic factory method in swift?如何快速编写通用工厂方法?
【发布时间】:2014-06-21 11:18:04
【问题描述】:

如果可能的话,我不知道如何编写调用其泛型类型的构造函数的方法,该构造函数继承自常见的已知基类

在操场上工作的示例:

// 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)

一个明显的解决方案是将创建委托给调用者,但这似乎很笨拙:

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

谢谢。

PS:createSome()->Base[] 赋值给 objs:Boomstick[] 类型不安全吗?

【问题讨论】:

标签: generics swift factory type-inference


【解决方案1】:

现在我没有关于为什么的答案,但是用初始化器定义一个协议似乎只管用:

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) }
}

并在您的 createSome() 函数中使用 A 而不是 Base

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"}

还尝试使用MyPodBase 并打印出预期的结果。 测试一下,让我知道它是否也适合你。

【讨论】:

  • 这不再起作用了。见stackoverflow.com/questions/26280176/…
  • 这个其实挺好的。它甚至可以用于优势:将基类提升为协议 => 更少的继承,更多的表达看起来像什么......谢谢! ...该死的(第二篇文章)... :-D
【解决方案2】:

从 Swift 5 开始,您可以编写:

protocol Printable: CustomStringConvertible { }

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

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

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

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

let objs : [Boomstick] = createSome()
objs.map{print($0)} // Base.Boomstick.1, Base.Boomstick.2, ...

【讨论】:

    猜你喜欢
    • 2020-09-28
    • 1970-01-01
    • 2023-04-09
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多