Inheritance 是否可以将Swift泛型类函数返回类型限制为相同的类或子类?
我正在Swift中扩展一个基类(我不控制的)。我想提供一个类函数来创建一个类型化为子类的实例。需要一个通用函数。但是,下面这样的实现不会返回预期的子类类型Inheritance 是否可以将Swift泛型类函数返回类型限制为相同的类或子类?,inheritance,swift,polymorphism,generics,Inheritance,Swift,Polymorphism,Generics,我正在Swift中扩展一个基类(我不控制的)。我想提供一个类函数来创建一个类型化为子类的实例。需要一个通用函数。但是,下面这样的实现不会返回预期的子类类型 class Calculator { func showKind() { println("regular") } } class ScientificCalculator: Calculator { let model: String = "HP-15C" override func showKind() { pr
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()
类计算器{
func showKind(){println(“常规”)}
}
类科学计算器:计算器{
let型号:String=“HP-15C”
重写func showKind(){println(“科学”)}
}
扩展计算器{
类func create()->T{
让实例=T()
返回实例
}
}
让sci:scientificalculator=scientificalculator.create()
sci.showKind()
调试器将T
报告为scientificalculator
,但sci
是Calculator
,调用sci.showKind()
返回“常规”
是否有一种方法可以使用泛型实现预期的结果,或者这是一个bug?在某个地方有一个bug-我的意思是,不是在您的代码中:) 这显然是一种通用方法:
class func create<T:Calculator>() -> T
结果是一样的
一个更有趣的观察:sci
是ScientificCalculator
类型的变量,但它指向Calculator
的一个实例。所以这个代码:
sci.model
编译,但生成运行时异常-因为基类中没有定义model
属性
这显然是一个编译器错误:一个超类的实例被分配给一个类型为其子类之一的变量——这是不可能的(尽管相反是可能的)
另外,请阅读我对aOk的回答,如果您控制了基类,您可能能够实现以下解决方法
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()
类计算器{
func showKind(){println(“常规”)}
必需的init(){}
}
类科学计算器:计算器{
let型号:String=“HP-15C”
重写func showKind(){println(\(model)-Scientific”)}
必需的init(){
super.init()
}
}
扩展计算器{
类func create()->T{
让klass:T.Type=T.self
返回klass()
}
}
让sci:scientificalculator=scientificalculator.create()
sci.showKind()
不幸的是,如果您不能控制基类,这种方法是不可能的。这并不能解释为什么您的泛型方法不起作用。我只是在找另一个选择 斯威夫特似乎已经用方便的初始值设定项取代了工厂方法。您可以创建一个新的方便初始值设定项,并将其添加到
计算器的扩展名中
extension Calculator {
convenience init(name: String) {
println(name)
self.init()
}
}
let reg = Calculator(name: "Reg")
reg.showKind() // "regular"
let sci = ScientificCalculator(name: "Sci")
sci.showKind() // "scientific"
更新后,我使用计算器作为返回类型,这毫无意义。它应该是Self,但仍然必须存在一个必需的init:
class Calculator {
func showKind() { println("regular") }
required init() {
}
}
class ScientificCalculator: Calculator {
let model: String = "HP-15C"
override func showKind() { println("scientific") }
}
extension Calculator {
class func create() -> Self {
return self()
}
}
var b = ScientificCalculator.create() // HP-15C
b.showKind()
除了肖恩·伍德沃德,如果计算器有(必需的)初始值设定项,它也能工作。不需要在子类中重写它
class Calculator {
required init() {
}
func showKind() { println("regular") }
}
class ScientificCalculator: Calculator {
let model: String = "HP-15C"
override func showKind() { println("scientific") }
}
extension Calculator {
class func create<T:Calculator>( type:T.Type ) -> T {
return type() as T
}
class func newInstance() -> Calculator {
return self()
}
}
var b = ScientificCalculator.newInstance() // HP-15C
b.showKind() // sientific
类计算器{
必需的init(){
}
func showKind(){println(“常规”)}
}
类科学计算器:计算器{
let型号:String=“HP-15C”
重写func showKind(){println(“科学”)}
}
扩展计算器{
类func create(类型:T.type)->T{
返回类型()作为T
}
类func newInstance()->计算器{
返回自我()
}
}
var b=ScientificCalculator.newInstance()//HP-15C
b、 showKind()//sientific
它使用游乐场为我返回计算器。Xcode 6.1.1?它也适用于我(控制台应用程序),但它不应该返回一个ScientificCalculator
。类型是Calculator createScientificCalculator:Calculator=>ScientificCalculator是类型Calculator。有理由不直接执行let sci=ScientificCalculator()
。您希望通过create()
方法获得什么?尝试了完全相同的方法并获得了确切的结果。我宁愿它是我代码中的一个bug。我也在尝试使用协议和类型别名来解决这个问题,但进展不太快。编译器警告类型别名不明确。我一定是做错了什么。关于如何使用协议达到预期效果有什么想法吗?@seanwoodward:你的意思是你使用了相同的方法,但得到了正确的预期结果(该实例实际上是ScientificCalculator
类型)?不,我不知道,但可能你不会解决这个问题——毕竟,对于必须在具体类中提供实现的协议,我没有得到“正确和预期”的结果。我得到了与“不太明确”方法相同的结果。非常令人失望。我讨厌回到任何对象和施法。当然,但我也不能控制所有的子类。通用方法是一个明确的要求。非常感谢您在这个问题上的努力。我没有对子类做任何事情。请原谅,你是在理论层面上提问,而我正试图理解你希望在实践层面上实现的目标。通过向现有初始值设定项未提供的基类添加新工厂方法,您希望获得什么?您的观点是正确的。我正试图以同样的方式处理这个问题。事实上,正是这种方法可能显示出希望。部分问题是初始值设定项依赖于将被重写的类函数。无法在我的便利初始化中调用self.dynamicType.classFunc()
。
class Calculator {
required init() {
}
func showKind() { println("regular") }
}
class ScientificCalculator: Calculator {
let model: String = "HP-15C"
override func showKind() { println("scientific") }
}
extension Calculator {
class func create<T:Calculator>( type:T.Type ) -> T {
return type() as T
}
class func newInstance() -> Calculator {
return self()
}
}
var b = ScientificCalculator.newInstance() // HP-15C
b.showKind() // sientific