sea*_*ard 5 generics polymorphism inheritance swift
我在Swift中扩展了一个基类(我无法控制的基类).我想提供一个类函数来创建一个类型为子类的实例.通用功能是必需的.但是,类似下面的实现不会返回预期的子类类型.
class Calculator {
func showKind() { println("regular") }
}
class ScientificCalculator: Calculator {
let model: String = "HP-15C"
override func showKind() { println("scientific") }
}
extension Calculator {
class func create<T:Calculator>() -> T {
let instance = T()
return instance
}
}
let sci: ScientificCalculator = ScientificCalculator.create()
sci.showKind()
Run Code Online (Sandbox Code Playgroud)
调试器报告T
的ScientificCalculator
,但是sci
是Calculator
和调用sci.showKind()
返回"常规".
有没有办法使用泛型达到预期的结果,还是一个bug?
好的,从开发人员论坛,如果您可以控制基类,您可能能够实现以下解决方案.
class Calculator {
func showKind() { println("regular") }
required init() {}
}
class ScientificCalculator: Calculator {
let model: String = "HP-15C"
override func showKind() { println("\(model) - Scientific") }
required init() {
super.init()
}
}
extension Calculator {
class func create<T:Calculator>() -> T {
let klass: T.Type = T.self
return klass()
}
}
let sci:ScientificCalculator = ScientificCalculator.create()
sci.showKind()
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果您无法控制基类,则无法使用此方法.
某个地方有一个错误 - 我的意思是,不是在你的代码中:)
这显然是一个通用方法:
class func create<T:Calculator>() -> T
Run Code Online (Sandbox Code Playgroud)
T
由返回值分配给的变量的类型推断,在您的情况下是ScientificCalculator
.
一个更有趣的案例。让我们修改该create
函数,使 的类型T
变得显式,而不管实例分配给的变量的类型如何:
class func create<T:Calculator>(type: T.Type) -> T
let sci: ScientificCalculator = ScientificCalculator.create(ScientificCalculator.self)
Run Code Online (Sandbox Code Playgroud)
结果是一样的。
一个更有趣的观察:sci
是一个类型变量ScientificCalculator
,但它指向 的一个实例Calculator
。所以这段代码:
sci.model
Run Code Online (Sandbox Code Playgroud)
model
编译,但生成运行时异常 - 因为基类中没有定义属性。
这显然是一个编译器错误:超类的实例被分配给其类型为其子类之一的变量 - 这永远不可能(尽管相反的情况也是可能的)
另请阅读我对类似问题的回答