Swift泛型不保留类型

rfr*_*lli 17 generics swift xcode6

我正在尝试基于指定的泛型类型转换和/或生成变量.我知道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()
Run Code Online (Sandbox Code Playgroud)

仍打印出"我是BaseClass"

还要注意基类中所需的init {}不再有效.

在此输入图像描述

rin*_*aro 15

此代码按预期工作.

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()
Run Code Online (Sandbox Code Playgroud)

代码库是从@GregoryHigley偷来的:)

标记init() {}required事情.这个保证init()是来自任何派生类的指定初始值设定项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()
Run Code Online (Sandbox Code Playgroud)

您知道这不起作用,因为IllegalDerivedClass 不继承init()初始化程序.

我想,这就是你问题的原因.

无论如何,谁的错?

  • 编译器应警告模棱两可.
  • 运行时应尝试DerivedClass()按照指定初始化T.
  • 调试器应该显示的instanceBaseClass实际的实例.

添加:

从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()
    }
}
Run Code Online (Sandbox Code Playgroud)

我完全不知道为什么我们需要这个,X上发生了什么(

新增:2014年10月18日

我发现这也有效:

    func doSomething() {
        var instance = (T.self as T.Type)()
        instance.printme()
    }
Run Code Online (Sandbox Code Playgroud)

增加日期:2015/02/10

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

我们不再需要(T.self as T.Type)()黑客攻击.只要有初始化程序就T()可以工作.Trequired init()

class Util<T: BaseClass> {
    func doSomething() {
        var instance = T()
        instance.printme()
    }
}
Run Code Online (Sandbox Code Playgroud)


Gre*_*ley 6

我创建了一个简化版的代码,如下所示:

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()
Run Code Online (Sandbox Code Playgroud)

这就解决了问题的本质.人们期望util.doSomething()打印"我是DerivedClass",但每次打印"我都是BaseClass".这必须是一个错误,因为没有合理的类型系统会以这种方式工作.

我认为你应该把它作为一个bug提交给Apple.