【问题标题】:Instantiate an object of a generic type in Swift在 Swift 中实例化一个泛型类型的对象
【发布时间】:2014-08-17 06:32:46
【问题描述】:

我正在 Swift 中实现一个类 Foo,它应该实例化 SuperBar 的给定 子类 的对象,例如Bar: SuperBar。我真的很喜欢 Swift 中的泛型,所以我尝试以这种方式实现它:

class Foo<T: SuperBar> {

    func instantiateObject() -> T {
        return T()
    }

}

class SuperBar {

}

class Bar: SuperBar {

}

let foo = Foo<Bar>()

let obj = foo.instantiateObject()

您可以在 Xcode Playground 中运行代码 sn-p 并观察 obj 的类型为 SuperBar 而不是 Bar,尽管当我 Alt 时它显示 Bar-点击常量名。

有什么想法吗? :)

【问题讨论】:

  • 这可能是当前版本的 Swift 的一个缺点;考虑filing a bug。如果您将类型作为参数传递,它似乎也不起作用,例如init(_ t: T.Type) { ... t() }

标签: generics swift


【解决方案1】:

将类init标记为required,然后调用init:

class SuperBar {
    required init() {
    }
}


class Foo<T: SuperBar> {

    func instantiateObject() -> T {
        return T.init()
    }

} 

【讨论】:

    【解决方案2】:

    如果您将required init() { } 添加到SuperBar,它可以正常工作。无论如何,应该始终需要该要求,因为您正在从变量类创建实例。

    它允许您使用不需要的初始化程序来创建它,这是一个错误。

    【讨论】:

    • 但是它初始化了一个垃圾(null)对象
    【解决方案3】:

    如果您确切知道泛型的类型,则可以强制转换它。

    let emptyObject:T = NSObject() as! T
    

    显然这违背了泛型类的目的,但它对某些默认值或基类功能很有用,就像我的例子一样。

    这也很危险,如果类型 T 不是 NSObject 会崩溃

    【讨论】:

    • 这对于所有非 NSObject 类型肯定会崩溃。
    【解决方案4】:
    • 使用protocol定义init方法的蓝图;
    • 采用这个Initializable协议的其他类必须实现init函数
    • 使用带有generic type的函数来创建一个类型的实例
    protocol Initializable {
        init()
    }
    
    class SuperBar : Initializable {
        required init() {
            print("init SuperBar")
        }
    }
    
    class Bar : SuperBar {
        required init() {
            print("init Bar")
        }
    }
    
    func createInstance<T>(type:T.Type) -> T where T:Initializable {
        return type.init()
    }
    
    

    测试:

    let a = createInstance(type: SuperBar.self)
    print("SuperBar: \(a.self)")
    let b = createInstance(type: Bar.self)
    print("Bar: \(b.self)")
    

    结果:

    init SuperBar
    SuperBar: __lldb_expr_22.SuperBar
    init Bar
    init SuperBar
    Bar: __lldb_expr_22.Bar
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-06
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2013-10-03
      • 2011-04-02
      相关资源
      最近更新 更多