一尘不染

Swift泛型不保留类型

swift

我正在尝试基于指定的泛型类型进行强制转换和/或生成一个变量。我知道并没有快速的类型擦除,但是除了泛型的指定条件(例如符合基类)外,泛型似乎并没有保留类型。看来我可以强制转换或初始化的只是基类。更奇怪的是,当我在调试器中时,泛型似乎对正确的类具有RawPointer,甚至变量看起来都像是正确的类型:

编辑:

从Xcode 6.1开始,这仍然是一个问题(简化的代码由Gregory Higley提供):

class BaseClass {
    func printme() -> Void {
        println("I am BaseClass")
    }
}

class DerivedClass : BaseClass {
    override func printme() -> Void {
        println("I am DerivedClass")
    }
}

class Util<T: BaseClass> {
    func doSomething() {
        var instance = T()
        instance.printme()
    }
}

var util = Util<DerivedClass>()
util.doSomething()

仍打印出“我是BaseClass”

还需要注意的是,基类中必需的init {}不再起作用。

在此处输入图片说明


阅读 251

收藏
2020-07-07

共1个答案

一尘不染

此代码按预期方式工作。

class BaseClass {

    required init() {} // <-- ADDED THIS

    func printme() -> Void {
        println("I am BaseClass")
    }
}

class DerivedClass : BaseClass {
    override func printme() -> Void {
        println("I am DerivedClass")
    }
}

class Util<T: BaseClass> {
    func doSomething() {
        var instance = T()
        instance.printme()
    }
}

var util = Util<DerivedClass>()
util.doSomething()

代码库从@GregoryHigley答案中被窃取了:)

标记init() {}required事物。这保证init()ANY 派生类的指定初始化器BaseClass

没有它,人们可能会制造出非法的子类,例如:

class IllegalDerivedClass : BaseClass {
    var name:String

    init(name:String) {
        self.name = name
        super.init()
    }

    override func printme() -> Void {
        println("I am DerivedClass")
    }
}

var util = Util<IllegalDerivedClass>()
util.doSomething()

您知道这是行不通的,因为IllegalDerivedClass
它不继承init()初始值设定项

我认为,这就是您遇到问题的原因。

反正那是谁的错

  • 编译器 应警告歧义。
  • 运行时 应该尝试初始化DerivedClass()与指定T
  • 调试器 应显示instance实际的实例BaseClass

添加:

从Xcode 6.1 GM 2开始,看来您需要做更多的工作。(除了required init() {}

class Util<T: BaseClass> {
    let theClass = T.self // store type itself to variable

    func doSomething() {
        var instance = theClass() // then initialize
        instance.printme()
    }
}

我绝对不知道为什么我们需要这个,X发生了什么(

添加:2014/10/18

我发现这也有效:

    func doSomething() {
        var instance = (T.self as T.Type)()
        instance.printme()
    }

添加:2015/02/10

从Xcode 6.3(6D520o)/ Swift 1.2开始

我们不再需要(T.self as T.Type)()hack。只要具有初始化程序就T()可以工作。T``required init()

class Util<T: BaseClass> {
    func doSomething() {
        var instance = T()
        instance.printme()
    }
}
2020-07-07