Downcasting with protocols and classes

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:

Downcasting with protocols and classes

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:

Downcasting with protocols and classes

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:

Downcasting with protocols and classes

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:

Downcasting with protocols and classes

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:

Downcasting with protocols and classes

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.225.213