Swift generics not preserving type

前端 未结 4 775
借酒劲吻你
借酒劲吻你 2020-11-28 11:23

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 pre

4条回答
  •  没有蜡笔的小新
    2020-11-28 11:44

    This code works as expected.

    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 {
        func doSomething() {
            var instance = T()
            instance.printme()
        }
    }
    
    var util = Util()
    util.doSomething()
    

    Code base are stolen from @GregoryHigley answer :)

    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()
    util.doSomething()
    

    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?

    • 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.

    ADDED:

    As of Xcode 6.1 GM 2, It seems, you need more work. (in addition to required init() {})

    class Util {
        let theClass = T.self // store type itself to variable
    
        func doSomething() {
            var instance = theClass() // then initialize
            instance.printme()
        }
    }
    

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

    ADDED:2014/10/18

    I found this also works:

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

    ADDED: 2015/02/10

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

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

    class Util {
        func doSomething() {
            var instance = T()
            instance.printme()
        }
    }
    

提交回复
热议问题