swift 多态性和动态类型的问题
Problem with swift polymorphism and dynamic type
我刚刚在 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
type(of: self) = TestClass2
T.Type = TestClass2
所以基本上当调用 testClass.run()
时,type(of: self)
会产生 TestClass
,这是我所期望的。问题是之后立即调用的通用函数 testGeneric
不知何故不适用于类型 TestClass
,而是使用 TestSuperClass
。
我个人的期望是
type(of: self) = TestClass
T.Type = TestClass
type(of: self) = TestClass2
T.Type = TestClass2
即,当通过 testClass.run()
.
调用时,通用函数 testGeneric
使用类型 TestClass
而不是 TestSuperClass
问题:
- 你对此有什么解释吗?
- 如何获得我想要的行为?
在 Swift 中,编译器想要在 编译时 知道哪个泛型类型 "infer"。因此,类型系统将绑定到静态类型。没有 动态类型推断 这样的东西。
因此编译器生成以下内容(见注释):
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.self
在您的情况下是 TestSuperClass
,因为这是编译器能够看到的:
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
回答第二个问题:你将无法更改返回数组的动态类型;它总是 [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
type(of: self) = TestClass
T.Type = TestSuperClass
TestSuperClass.init
TestClass.init
type(of: newObj) = TestClass
type(of: self) = Array < TestSuperClass >
[__lldb_expr_21.TestClass]
我刚刚在 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
type(of: self) = TestClass2
T.Type = TestClass2
所以基本上当调用 testClass.run()
时,type(of: self)
会产生 TestClass
,这是我所期望的。问题是之后立即调用的通用函数 testGeneric
不知何故不适用于类型 TestClass
,而是使用 TestSuperClass
。
我个人的期望是
type(of: self) = TestClass
T.Type = TestClass
type(of: self) = TestClass2
T.Type = TestClass2
即,当通过 testClass.run()
.
testGeneric
使用类型 TestClass
而不是 TestSuperClass
问题:
- 你对此有什么解释吗?
- 如何获得我想要的行为?
在 Swift 中,编译器想要在 编译时 知道哪个泛型类型 "infer"。因此,类型系统将绑定到静态类型。没有 动态类型推断 这样的东西。
因此编译器生成以下内容(见注释):
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.self
在您的情况下是 TestSuperClass
,因为这是编译器能够看到的:
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
回答第二个问题:你将无法更改返回数组的动态类型;它总是 [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
type(of: self) = TestClass
T.Type = TestSuperClass
TestSuperClass.init
TestClass.init
type(of: newObj) = TestClass
type(of: self) = Array < TestSuperClass >
[__lldb_expr_21.TestClass]