我试图更深入地了解类型转换,但不了解为什么在此示例中必须这样做:
class Animal { }
class Fish: Animal { }
class Dog: Animal {
func makeNoise() {
print("Woof!")
}
}
let pets = [Fish(), Dog(), Fish(), Dog()]
我正在阅读该代码以检查上述数组中的类型,我需要运行以下代码:
for pet in pets {
if let dog = pet as? Dog {
dog.makeNoise()
}
}
并且以下代码将崩溃:
for pet in pets {
if pet == Dog() {
pet.makeNoise()
}
}
它返回以下错误:
error: Learn Swift.playground:24:13: error: value of type 'Animal' has no member 'makeNoise'
pet.makeNoise()
~~~ ^~~~~~~~~
那是为什么?难道最后那段代码只是检查数组中的项是否是Dog()?
当前,我的猜测是我不完全了解for循环中“ pet”的隐式类型。我假设它只是根据数组中项目的类型猜测类型,在我们的例子中是对象。
答案 0 :(得分:1)
检查数组pets
的类型:应为[Animal]
/。动物无法发出声音,因此您需要明确检查它是否为狗。本质上,您已经将Dog
的类型与其他Animals
装在异类数组中而丢失了。在动物上调用makeNoise()
是没有意义的,因此编译器会强制您在调用Dog
之前检查数组的元素实际上是makeNoise()
。
答案 1 :(得分:1)
运行此行
print(type(of: pets))
它显示Array<Animal>
。基类是数组中各项的公分母。
在第二个示例中,您应该遇到另一个编译器错误
二进制运算符'=='不能应用于类型为'动物'和'狗'的操作数
尽管如此,但没有类型强制转换pet
仍然Animal
,并且'Animal'没有成员'makeNoise'
答案 2 :(得分:0)
首先,在检查实例类型时使用is
键盘。例如if pet is Dog { ... }
,您当前正在冗余地初始化它的新对象。
因此,当您问if pet is Dog { ... }
时,您只是在基于该语句检索布尔值,但这并没有使编译器将pet
称为Dog
。
相反,当您说if let dog = pet as? Dog { ... }
时,您正在创建类型为Dog?
的新值,这使编译器将其称为Dog
。