我在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 - 单击常量名称。
任何想法?:)
答案 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