快速多态和动态类型的问题

时间:2018-12-19 13:51:10

标签: swift inheritance dynamic polymorphism dynamictype

在多态和动态类型方面,我刚刚在swift的继承处理中遇到了一个奇怪的行为。以下代码显示了我遇到的问题,基本上是:动态类型可以正确识别(由print("type(of: self) = \(classType)")打印),但是通用函数testGeneric使用错误的类型。

class Global {
    static func testGeneric<T: TestSuperClass>(of type: T.Type) {
        print("T.Type = \(T.self)")
    }
}

class TestSuperClass {
    func run() {
        let classType = type(of: self)
        print("type(of: self) = \(classType)")
        Global.testGeneric(of: classType)
    }
}

class TestClass: TestSuperClass {

}

class TestClass2: TestSuperClass {
    override func run() {
        let classType = type(of: self)
        print("type(of: self) = \(classType)")
        Global.testGeneric(of: classType)
    }
}

let testClass = TestClass()
let testClass2 = TestClass2()

testClass.run()
testClass2.run()

打印的输出是

  

type(of:self)= TestClass
  T.Type = TestSuperClass
  类型(of:self)= TestClass2
  T.Type = TestClass2

因此,基本上,在调用testClass.run()时,type(of: self)会产生TestClass,这是我所期望的。然后问题是泛型函数testGeneric(此后立即被调用)在某种程度上不适用于类型TestClass,而是使用TestSuperClass

我个人期望的是

  

type(of:self)= TestClass
  T.Type = TestClass
  类型(of:self)= TestClass2
  T.Type = TestClass2

即,通过testGeneric调用时,泛型函数TestClass使用类型TestSuperClass而不是testClass.run()

问题:
-你有解释吗?
-如何获得自己的想法?

2 个答案:

答案 0 :(得分:2)

在Swift中,编译器希望在编译时知道要“推断”的泛型类型。因此,类型系统将绑定到静态类型。没有动态类型推断这样的东西。

因此,编译器会生成以下内容(请参见注释):

class TestSuperClass {
    func run() {
        let classType = type(of: self)  // static MetaType TestSuperClass.Type
        print("type(of: self) = \(classType)") // dynamic type: TestClass
        Global.testGeneric(of: classType)  // infer to static type, i.e. testGeneric<TestSuperClass>
    }
}

结果,在您的情况下,T.selfTestSuperClass,因为这是编译器能够看到的:

static func testGeneric<T: TestSuperClass>(of type: T.Type) {
    print("T.Type = \(T.self)")
}

您可能想要的是以下内容:

static func testGeneric<T: TestSuperClass>(of type: T.Type) {
    print("T.Type = \(type)")
}

在这里,您不打印T的类型,而是打印参数type的(动态)值,在您的情况下为TestClass

答案 1 :(得分:1)

要回答第二个问题:您将无法更改重新设置数组的动态类型;它将始终为[TestSuperClass]-尽管它将包含TestClass个对象:

class Global {
    static func testGeneric<T: TestSuperClass>(of type: T.Type) {
        print("T.Type = \(T.self)")
    }
    static func returnObjects<T: TestSuperClass>(of theType: T.Type) -> [T] {
        let newObj = theType.init()
        let newObjType = type(of:newObj)
        print("type(of: newObj) = \(newObjType)")
        return [newObj]
    }
}

class TestSuperClass {
    required init() {
        print ("TestSuperClass.init")
    }

    func run() {
        let classType = type(of: self)
        print("type(of: self) = \(classType)")
        Global.testGeneric(of: classType)
        let array = Global.returnObjects(of: classType)
        let arrayType = type(of:array)
        print("type(of: self) = \(arrayType)")

        print (array)
    }
}

class TestClass: TestSuperClass {
    required init() {
        super.init()
        print("TestClass.init")
    }

}

let testClass = TestClass()
testClass.run()
  

TestSuperClass.init
  TestClass.init
  类型(of:self)= TestClass
  T.Type = TestSuperClass
  TestSuperClass.init
  TestClass.init
  类型(of:newObj)= TestClass
  type(of:self)=数组
  [__lldb_expr_21.TestClass]