为什么在循环中检查类型时需要类型转换?
Why is typecasting necessary when checking types in loops?
我试图更深入地理解类型转换,但不明白为什么在这个例子中有必要:
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()
}
}
它returns出现以下错误:
error: Learn Swift.playground:24:13: error: value of type 'Animal' has no member 'makeNoise'
pet.makeNoise()
~~~ ^~~~~~~~~
这是为什么?最后一段代码不会只是检查数组中的项目是否是 Dog() 吗?
目前,我的猜测是我没有完全理解for循环中"pet"的隐式类型。我假设它只是根据数组中项目的类型猜测类型,在我们的例子中是一个对象。
检查数组的类型pets
:应该是[Animal]
/。动物不能发出声音,因此您需要明确检查它是否是狗。本质上,通过将 Dog
与其他 Animals
装箱在异构数组中,您丢失了它的类型。在 Animal 上调用 makeNoise()
没有意义,因此编译器会强制您在调用 makeNoise()
.[=17 之前检查数组的元素实际上是 Dog
=]
当你运行这一行
print(type(of: pets))
显示Array<Animal>
。基数 class 是数组中各项的公分母。
在你的第二个例子中你应该得到另一个编译器错误
Binary operator '==' cannot be applied to operands of type 'Animal' and 'Dog'
然而没有类型转换 pet
仍然是 Animal
而 'Animal' 没有成员 'makeNoise'
首先,检查实例类型时使用is
键盘。例如if pet is Dog { ... }
,您目前只是在冗余地初始化它的一个新对象。
那么,当您询问 if pet is Dog { ... }
时,您只是根据该语句检索布尔值,但它不会使编译器将 pet
引用为 Dog
.
相反,当您说 if let dog = pet as? Dog { ... }
时,您正在创建类型 Dog?
的新值,这使得编译器将其称为 Dog
.
我试图更深入地理解类型转换,但不明白为什么在这个例子中有必要:
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()
}
}
它returns出现以下错误:
error: Learn Swift.playground:24:13: error: value of type 'Animal' has no member 'makeNoise'
pet.makeNoise()
~~~ ^~~~~~~~~
这是为什么?最后一段代码不会只是检查数组中的项目是否是 Dog() 吗?
目前,我的猜测是我没有完全理解for循环中"pet"的隐式类型。我假设它只是根据数组中项目的类型猜测类型,在我们的例子中是一个对象。
检查数组的类型pets
:应该是[Animal]
/。动物不能发出声音,因此您需要明确检查它是否是狗。本质上,通过将 Dog
与其他 Animals
装箱在异构数组中,您丢失了它的类型。在 Animal 上调用 makeNoise()
没有意义,因此编译器会强制您在调用 makeNoise()
.[=17 之前检查数组的元素实际上是 Dog
=]
当你运行这一行
print(type(of: pets))
显示Array<Animal>
。基数 class 是数组中各项的公分母。
在你的第二个例子中你应该得到另一个编译器错误
Binary operator '==' cannot be applied to operands of type 'Animal' and 'Dog'
然而没有类型转换 pet
仍然是 Animal
而 'Animal' 没有成员 'makeNoise'
首先,检查实例类型时使用is
键盘。例如if pet is Dog { ... }
,您目前只是在冗余地初始化它的一个新对象。
那么,当您询问 if pet is Dog { ... }
时,您只是根据该语句检索布尔值,但它不会使编译器将 pet
引用为 Dog
.
相反,当您说 if let dog = pet as? Dog { ... }
时,您正在创建类型 Dog?
的新值,这使得编译器将其称为 Dog
.