Now, we will take advantage of the capability that Swift offers us to extend an existing class to add specific members. In this case, we will add an instance method to the previously defined AngryCat
class. The following lines add the doSomethingWith
method to the existing AngryCat
class. The code file for the sample is included in the swift_3_oop_chapter_05_11
folder:
public extension AngryCat { public func doSomethingWith(cat: AngryCat) { if let angryCatAlien = cat as? AngryCatAlien { angryCatAlien.appear() } else if let angryCatKnight = cat as? AngryCatKnight { angryCatKnight.unsheathSword() } else if let angryCatWizard = cat as? AngryCatWizard { print("My spell power is (angryCatWizard.spellPower)") } else { print("This AngryCat doesn't have cool skills.") } } }
The doSomethingWith
method receives an AngryCat
instance (cat
) and uses the conditional type casting operator (as?
) to return an optional value of the type that it tries to cast cat
to. In case cat
is an instance of AngryCatAlien
or of any potential subclass of AngryCatAlien
, the first type cast succeeds and the code calls the appear
method for the cat
type cast to an AngryCatAlien
instance, which is saved in the angryCatAlien
reference constant, as follows:
if let angryCatAlien = cat as? AngryCatAlien { angryCatAlien.appear()
In case the conditional type cast to AngryCatAlien
fails, the code uses the conditional type casting operator (as?
) and tries to cast cat
to AngryCatKnight
. In case cat
is an instance of AngryCatKnight
or an instance of any potential subclass of AngryCatKnight
, the conditional type cast succeeds, and the code calls the unsheathSword
method for the cat
type cast to an AngryCatKnight
instance, which is saved in the angryCatKnight
reference constant:
} else if let angryCatKnight = cat as? AngryCatKnight { angryCatKnight.unsheathSword()
In case the conditional type cast to AngryCatKnight
fails, the code uses the conditional type casting operator (as?
) and tries to cast cat
to AngryCatWizard
. In case cat
is an instance of AngryCatWizard
or of any potential subclass of AngryCatWizard
, the conditional type cast succeeds, and the code prints a message indicating the spellPower
value for the cat
type cast to an AngryCatWizard
instance, which is saved in the angryCatWizard
reference constant, as follows:
} else if let angryCatWizard = cat as? AngryCatWizard { print("My spell power is (angryCatWizard.spellPower)")
Finally, if the last conditional type cast to AngryCatKnight
fails, it means that the cat
instance just belongs to AngryCat
, so the code prints a message indicating that AngryCat
doesn't have cool skills.
Now, we will take advantage of the doSomethingWith
instance method added to the AngryCat
class and call it in instances of AngryCat
and its subclasses, which we created before we declared the extension. We will call the doSomethingWith
method for the AngryCat
instance named garfield
and use it the following arguments:
misterAlien
: This is an instance of the AngryCatAlien
classcamelot
: This is an instance of the AngryCatKnight
classgandalf
: This is an instance of the AngryCatWizard
classgarfield
: This is an instance of the AngryCat
classThe following four lines call the doSomethingWith
method in the Playground with the previously enumerated arguments. The code file for the sample is included in the swift_3_oop_chapter_05_11
folder:
garfield.doSomethingWith(cat: misterAlien) garfield.doSomethingWith(cat: camelot) garfield.doSomethingWith(cat: gandalf) garfield.doSomethingWith(cat: garfield)
The next lines show the output generated in the Playground. Each call triggers a different type cast and calls a method of the type cast instance:
I'm Mr. Alien and you can see my 3 eyes. Sir Camelot unsheaths his sword. Sword power: 100. Sword weight: 30. My spell power is 100 This AngryCat doesn't have cool skills.
The following screenshot shows that the execution of the four methods generates the doSomethingWith
method to execute code in each usage of the conditional type cast operator. Note the values displayed on the right-hand side of each line included within the curly braces after each conditional type cast. The lines that call the methods just display the type cast instance types, AngryCatAlien
and AngryCatKnight
, and the lines that call the print
method display the generated output on the right-hand side:
18.224.54.255