I'm trying to more deeply understand typecasting, and don't understand why it's necessary in this example:
class Animal { }
class Fish: Animal { }
class Dog: Animal {
func makeNoise() {
print("Woof!")
}
}
let pets = [Fish(), Dog(), Fish(), Dog()]
I'm reading that to check the type in the above array, I need to run the following code:
for pet in pets {
if let dog = pet as? Dog {
dog.makeNoise()
}
}
And that the following code would crash:
for pet in pets {
if pet == Dog() {
pet.makeNoise()
}
}
It returns the following error:
error: Learn Swift.playground:24:13: error: value of type 'Animal' has no member 'makeNoise'
pet.makeNoise()
~~~ ^~~~~~~~~
Why is that? Wouldn't that last block of code just check if the item in the array is Dog()?
Currently, my guess is that I don't fully understand the implicit type of "pet" in the for loop. I've assumed that it just guesses the type based on the type of items in the array, which in our case is an Object.
When you run this line
print(type(of: pets))
it displays Array<Animal>
. The base class is the common denominator of the items in the array.
In your second example you should get another compiler error
Binary operator '==' cannot be applied to operands of type 'Animal' and 'Dog'
Nevertheless without a type cast pet
remains Animal
and 'Animal' has no member 'makeNoise'