Combining inheritance and protocols

We can combine class inheritance with protocol conformance. The following lines show the code for a new AngryCatAlien class that inherits from the AngryCat class and conforms to the Alien protocol. Note that the class declaration includes the superclass (AngryCat) and the implemented protocol (Alien) separated by a comma after the colon (:). The code file for the sample is included in the swift_3_oop_chapter_05_09 folder:

    open class AngryCatAlien : AngryCat, Alien { 
      open var numberOfEyes: Int = 0 
     
      init (nickName: String, age: UInt, fullName: String, 
      initialScore: UInt, x: UInt, y: UInt, numberOfEyes: Int) { 
        super.init(nickName: nickName, age: age, fullName: fullName, 
        initialScore: initialScore, x: x, y: y) 
        self.numberOfEyes = numberOfEyes 
      } 
     
      open func appear() { 
        print("I'm (fullName) and you can see my (numberOfEyes) 
        eyes.") 
      } 
     
      open func disappear() { 
        print("(fullName) disappears.") 
      } 
    } 

As a result of the previous code, we have a new class named AngryCatAlien that conforms to the following three protocols:

  • ComicCharacter: This is implemented by the AngryCat superclass and inherited by AngryCatAlien
  • GameCharacter: This is implemented by the AngryCat superclass and inherited by AngryCatAlien
  • Alien: This is implemented by AngryCatAlien

The initializer adds a numberOfEyes argument to the argument list defined in the base initializer, that is, the initializer defined in the AngryCat superclass. In this case, the initializer calls the base initializer (self.init) and then initializes the numberOfEyes property with the value received in the numberOfEyes argument. The class implements the appear and disappear methods required by the Alien protocol.

The following lines show the code for a new AngryCatWizard class that inherits from the AngryCat class and implements the Wizard protocol. Note that the class declaration includes the superclass (AngryCat) and the implemented protocol (Wizard) separated by a comma after the colon (:). The code file for the sample is included in the swift_3_oop_chapter_05_09 folder:

    open class AngryCatWizard: AngryCat, Wizard { 
      open var spellPower: Int = 0 
 
      open func disappear(alien: Alien) { 
        print("(fullName) uses his (spellPower) spell power to make 
        the alien with (alien.numberOfEyes) eyes disappear.") 
      } 
  
      init (nickName: String, age: UInt, fullName: String, 
      initialScore: UInt, x: UInt, y: UInt, spellPower: Int) { 
        super.init(nickName: nickName, age: age, fullName: fullName, 
        initialScore: initialScore, x: x, y: y) 
        self.spellPower = spellPower 
      } 
    } 

As with the AngryCatAlien class, the new AngryCatWizard class implements three protocols. Two of these protocols are implemented by the AngryCat superclass and inherited by AngryCatWizard: ComicCharacter and GameCharacter. The AngryCatWizard class adds the implementation of the Wizard protocol.

The initializer adds a spellPower argument to the argument list defined in the base constructor (super.init), which is the constructor defined in the AngryCat superclass. The constructor calls the base constructor and then initializes the spellPower property with the value received in the spellPower argument. The class implements the disappear method, which receives an Alien instance as an argument, required by the Wizard protocol.

The disappear method receives an Alien as an argument. Thus, any instance of AngryCatAlien would qualify as an argument for this method, that is, any instance of any class that conforms to the Alien protocol.

The following lines show the code for a new AngryCatKnight class, which inherits from the AngryCat class and implements the Knight protocol. Note that the class declaration includes the superclass (AngryCat) and implemented protocol (Knight) separated by a comma after the colon (:). The code file for the sample is included in the swift_3_oop_chapter_05_09 folder:

    open class AngryCatKnight : AngryCat, Knight { 
      open var swordPower: Int = 0 
      open var swordWeight: Int = 0 
     
      private func writeLinesAboutTheSword() { 
        print("(fullName) unsheaths his sword.") 
        print("Sword power: (swordPower). Sword weight: 
        (swordWeight).") 
      } 
     
      open func unsheathSword() { 
        writeLinesAboutTheSword() 
      } 
     
      open func unsheathSword(target: Alien) { 
        writeLinesAboutTheSword() 
        print("The sword targets an alien with (target.numberOfEyes) 
        eyes.") 
      } 
     
      init (nickName: String, age: UInt, fullName: String, 
      initialScore: UInt, x: UInt, y: UInt, swordPower: Int, 
      swordWeight: Int) { 
        super.init(nickName: nickName, age: age, fullName: fullName, 
        initialScore: initialScore, x: x, y: y) 
        self.swordPower = swordPower 
        self.swordWeight = swordWeight 
      } 
    } 

As with the two previously coded classes inherited from the AngryCat class and conforming to the protocols, the new AngryCatKnight class implements three protocols. Two of these protocols are implemented by the AngryCat superclass and inherited by AngryCatKnight: ComicCharacter and GameCharacter. The AngryCatKnight class adds the implementation of the Knight protocol.

The initializer adds the swordPower and swordWeight arguments to the argument list defined in the base initializer (base.init), which is the constructor defined in the AngryCat superclass. The initializer calls the base initializer (base.init) and then initializes the swordPower and swordWeight properties with the values received in the swordPower and swordHeight arguments.

The class implements the two versions of the unsheathSword method required by the Knight protocol. Both methods call the private writeLinesAboutTheSword method, and the overloaded version that receives Alien as an argument prints an additional message about the alien that the sword has as a target---specifically, the number of eyes.

The following table summarizes the list of protocols to which each of the classes we created conform:

Class name

Conforms to the following protocol(s)

AngryDog

ComicCharacter

AngryCat

ComicCharacter and GameCharacter

AngryCatAlien

ComicCharacter, GameCharacter, and Alien

AngryCatWizard

ComicCharacter, GameCharacter, and Wizard

AngryCatKnight

ComicCharacter, GameCharacter, and Knight

The following simplified UML diagram shows the hierarch tree for the classes and their relationships with protocols:

Combining inheritance and protocols

The following UML diagram shows the protocols and the classes with their properties and methods. We can use the diagram to understand all the things that we will analyze with the next code samples based on the usage of these classes and the previously defined protocols:

Combining inheritance and protocols

The following lines create one instance of each of the previously created classes. The code file for the sample is included in the swift_3_oop_chapter_05_09 folder:

    var angryDog1 = AngryDog(nickName: "Bailey") 
    var angryCat1 = AngryCat(nickName: "Bella", age: 3, 
    fullName: "Mrs. Bella", initialScore: 20, x: 10, y: 10) 
    var angryCatAlien1 = AngryCatAlien(nickName: "Lucy", age: 4, 
    fullName: "Mrs. Lucy", initialScore: 50, x: 20, y: 10, 
    numberOfEyes: 3) 
    var angryCatWizard1 = AngryCatWizard(nickName: "Daisy", age: 4, 
    fullName: "Mrs. Daisy", initialScore: 50, x: 20, y: 10, 
    spellPower: 6) 
    var angryCatKnight1 = AngryCatKnight(nickName: "Maggie", age: 3, 
    fullName: "Mrs. Maggy", initialScore: 1300, x: 40, y: 10, 
    swordPower: 7, swordWeight: 5) 

The following table summarizes the instance name and its class name:

Instance name

Class name

angryDog1

AngryDog

angryCat1

AngryCat

angryCatAlien1

AngryCatAlien

angryCatWizard1

AngryCatWizard

angryCatKnight

AngryCatKnight

Now, we will evaluate many expressions that use the is keyword to determine whether the instances are an instance of the specified class or conform to a specific protocol. Note that all the expressions are evaluated to true because every instance is of the type specified on the right-hand side after the is keyword. The specified types are the main class for the instance, its superclass, or a class that conforms to the protocol.

For example, angryCatWizard1 is an instance of AngryCatWizard. In addition, angryCatWizard1 belongs to AngryCat because AngryCat is the superclass of the AngryCatWizard class. It is also true that angryCatWizard1 conforms to three protocols: ComicCharacter, GameCharacter, and Wizard. The superclass of AngryCatWizard---that is, AngryCat---conforms to two of these protocols: ComicCharacter and GameCharacter. Therefore, AngryCatWizard inherits the protocol conformance. Finally, the AngryCatWizard class not only inherits from AngryCat but also conforms to the Wizard protocol. If we execute the following lines in the Playground, all of them will print true as a result. The code file for the sample is included in the swift_3_oop_chapter_05_09 folder:

    print(angryDog1 is AngryDog) 
    print(angryDog1 is ComicCharacter) 
 
    print(angryCat1 is AngryCat) 
    print(angryCat1 is ComicCharacter) 
    print(angryCat1 is GameCharacter) 
 
    print(angryCatAlien1 is AngryCat) 
    print(angryCatAlien1 is AngryCatAlien) 
    print(angryCatAlien1 is ComicCharacter) 
    print(angryCatAlien1 is GameCharacter) 
    print(angryCatAlien1 is Alien) 
 
    print(angryCatWizard1 is AngryCat) 
    print(angryCatWizard1 is AngryCatWizard) 
    print(angryCatWizard1 is ComicCharacter) 
    print(angryCatWizard1 is GameCharacter) 
    print(angryCatWizard1 is Wizard) 
 
    print(angryCatKnight1 is AngryCat) 
    print(angryCatKnight1 is AngryCatKnight) 
    print(angryCatKnight1 is ComicCharacter) 
    print(angryCatKnight1 is GameCharacter) 
    print(angryCatKnight1 is Knight) 

The following screenshot shows the result of executing the previous lines in the Playground. Note that the Playground uses a warning icon to let us know that all the expressions that include the is keyword will always be evaluated to true. In these cases, the compiler generates a warning:

Combining inheritance and protocols

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

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