Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Inheritance 是否可以将Swift泛型类函数返回类型限制为相同的类或子类?_Inheritance_Swift_Polymorphism_Generics - Fatal编程技术网

Inheritance 是否可以将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

我正在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()
类计算器{
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
属性

这显然是一个编译器错误:一个超类的实例被分配给一个类型为其子类之一的变量——这是不可能的(尽管相反是可能的)

另外,请阅读我对a

Ok的回答,如果您控制了基类,您可能能够实现以下解决方法

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