The ComicCharacter
protocol defines one of the method requirements for the drawSpeechBalloon
method with destination
as an argument of the ComicCharacter
type, which is the same type that the protocol defines. The following is the first line in our sample code that called this method:
brian.drawSpeechBalloon(destination: merlin, message: "How do you do?")
We called the method defined within the AngryDog
class because brian
is an instance of AngryDog
. We passed an AngryDog
instance, merlin
, to the destination
argument. The method works with the destination
argument as an instance that conforms to the ComicCharacter
protocol; therefore, whenever we reference the destination variable, we will only be able to see what the ComicCharacter
type defines.
We can easily understand what happens under the hood when Swift downcasts a type from its original type to a target type, such as a protocol to which the class conforms. In this case, AngryDog
is downcasted to ComicCharacter
. If we enter the following code in the Playground, Xcode will enumerate the members for the AngryDog
instance named merlin
:
merlin.
Xcode will display the following members:
Void drawSpeechBalloon(destination: ComicCharacter, message: String) Void drawSpeechBalloon(message: String) Void drawThoughtBalloon(message: String) String nickName Void speak(message: String) Void think(message: String)
The following screenshot shows the members enumerated in the Playground for merlin
, which is an AngryDog
instance:
If we enter the following code in the Playground, the as
downcast operator forces the downcast to the ComicCharacter
protocol type; therefore, Xcode will only enumerate the members for the AngryDog
instance named merlin
that are required members in the ComicCharacter
protocol:
(merlin as ComicCharacter).
Xcode will display the following members:
Void drawSpeechBalloon(destination: ComicCharacter, message: String) Void drawSpeechBalloon(message: String) Void drawThoughtBalloon(message: String) String nickName
Note that the two methods that are defined in the AngryDog
class but aren't required in the ComicCharacter
protocol aren't visible: speak
and think
. The following screenshot shows the members enumerated in the Playground for the merlin
instance's downcast to ComicCharacter
:
Now, let's analyze another scenario in which an instance is downcasted to one of the protocols to which it conforms. The GameCharacter
protocol defines a method requirement for the intersects
method with character
as an argument of the GameCharacter
type, which is the same type that the protocol defined. The following is the first line in our sample code that called this method:
if (misterAlien.intersects(character: garfield)) {
We called the method defined within the AngryCat
class because misterAlien
is an instance of AngryCatAlien
, which inherits the method implementation from the AngryCat
class. We passed an AngryCat
instance, garfield
, to the character
argument. The method works with the character
argument as an instance that conforms to the GameCharacter
protocol; therefore, whenever we reference the destination variable, we will only be able to see what the GameCharacter
type defines.
In this case, AngryCat
is downcasted to GameCharacter
. If we enter the following code in the Playground, Xcode will enumerate the members for the AngryCat
instance named garfield
:
garfield.
Xcode will display the following members:
UInt age Void drawAt(x: UInt, y: UInt) Void drawSpeechBalloon(destination: ComicCharacter, message: String) Void drawSpeechBalloon(message: String) Void drawThoughtBalloon(message: String) String fullName Bool intersects(character: GameCharacter) Void moveTo(x: UInt, y: UInt) String nickName UInt score UInt x UInt y
The following screenshot shows the first members enumerated in the Playground for garfield
, which is an AngryCat
instance:
If we enter the following code in the Playground, the as
downcast operator forces the downcast to the GameCharacter
protocol type; therefore, Xcode will only enumerate those members for the AngryCat
instance named garfield
that are required members in the GameCharacter
protocol:
(garfield as GameCharacter).
Xcode will display the following members:
Void drawAt(x: UInt, y: UInt) String fullName Bool intersects(character: GameCharacter) Void moveTo(x: UInt, y: UInt) UInt score UInt x UInt y
Note that the list of members has been reduced to the properties and members required in the GameCharacter
protocol. The following screenshot shows the members enumerated in the Playground for the garfield
instance's downcast to GameCharacter
:
We can use the as
operator to force a cast of the previous expression to the original type, that is, to the AngryCat
type. This way, Xcode will enumerate all the members of the AngryCat
instance again:
((garfield as GameCharacter) as AngryCat).
Xcode will display the following members---that is, all the members that Xcode enumerated when we worked with garfield
---without any kind of casting:
UInt age Void drawAt(x: UInt, y: UInt) Void drawSpeechBalloon(destination: ComicCharacter, message: String) Void drawSpeechBalloon(message: String) Void drawThoughtBalloon(message: String) String fullName Bool intersects(character: GameCharacter) Void moveTo(x: UInt, y: UInt) String nickName UInt score UInt x UInt y
The following screenshot shows the first members enumerated in the Playground for garfield
downcast to GameCharacter
and when it is casted back to an AngryCat
instance:
3.139.107.210