Swift 泛型不保留类型 [英] Swift generics not preserving type

查看:36
本文介绍了Swift 泛型不保留类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying cast and/or generate a variable based upon the specified generic type. I understand there is no type erasure in swift, but it doesn't seem like the generics preserve type other than the specified conditions of the generic e.g. conforming to a base class. It seems like all i can cast or initialize is the base class. What's even more strange is when i'm in the debugger the generic appears to have a RawPointer to the correct class and even the variables look like they're of the right type:

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

As of Xcode 6.1 this is still an issue (simplified code courtesy of 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()

仍然打印出I am BaseClass"

Still prints out "I am BaseClass"

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

Also would like to note that required init{} in the base class no longer works.

推荐答案

此代码按预期工作.

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 答案中窃取的 :)

Code base are stolen from @GregoryHigley answer :)

init() {} 标记为 required 做到了.这保证了 init()BaseClass 派生类的 ANY 的指定初始化器.

Marking init() {} as required did the thing. This guarantees init() is the designated initializer of ANY derived class from BaseClass.

没有它,可以创建非法的子类,例如:

Without it, one can make illegal subclass like:

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()初始化器.

You know this doesn't work because IllegalDerivedClass doesn't inherit init() initializer.

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

I think, that is the reason of your problem.

无论如何,这是谁的错?

Anyway, whose fault is that?

  • 编译器应对歧义发出警告.
  • Runtime 应该尝试按照 T 的规定初始化 DerivedClass().
  • Debugger 应该显示 instanceBaseClass 的实际实例.
  • Compiler should warn about ambiguousness.
  • Runtime should try to initialize DerivedClass() as specified with T.
  • Debugger should show instance is a instance of BaseClass as it actually is.

添加:

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

As of Xcode 6.1 GM 2, It seems, you need more work. (in addition to 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(

I have absolutely no idea why we need this, what's going on X(

添加时间:2014/10/18

ADDED:2014/10/18

我发现这也有效:

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

<小时>

添加:2015/02/10

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

As of Xcode Version 6.3 (6D520o) / Swift 1.2

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

We no longer need (T.self as T.Type)() hack. Just T() works as long as T has required init() initializer.

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

这篇关于Swift 泛型不保留类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆