在Swift中实例化泛型类型的对象

时间:2014-08-17 06:32:46

标签: generics swift

我在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中运行代码段并观察obj类型为SuperBar而不是Bar,但是当我时它会显示Bar Alt - 单击常量名称。

任何想法?:)

4 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:5)

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

class SuperBar {
    required init() {
    }
}


class Foo<T: SuperBar> {

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

} 

答案 2 :(得分:1)

  • 使用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

答案 3 :(得分:0)

如果你确切知道通用的类型,你可以强制施放它。

let emptyObject:T = NSObject() as! T

显然这会破坏泛型类的用途,但它对于某些默认值或基类功能非常有用。

如果类型T不是NSObject

,这也很危险并会崩溃