Taking advantage of the multiple inheritance of protocols

Swift doesn't allow us to declare a class with multiple base classes or superclasses, so there is no support for multiple inheritance of classes. A subclass can inherit just from one class. However, a class can conform to one or more protocols. In addition, we can declare classes that inherit from a superclass and conform to one or more protocols. Thus, we can combine class-based inheritance with protocols.

We want the AngryCat class to conform to both the ComicCharacter and GameCharacter protocols. Thus, we want to use any AngryCat instance as both a comic character and a game character. In order to do so, we must change the class declaration and add the GameCharacter protocol to the list of protocols that the class conforms to and declare all the members included in this added protocol within the class.

The following lines show the new class declaration that specifies that the AngryCat class conforms to both the ComicCharacter and GameCharacter protocols. The code file for the sample is included in the swift_3_oop_chapter_05_07 folder:

    open class AngryCat: ComicCharacter, GameCharacter { 

After changing the class declaration, the Playground execution will fail because the AngryCat class doesn't implement the members required by the GameCharacter protocol. The Swift compiler generates the following errors and notes:

error: type 'AngryCat' does not conform to protocol 'GameCharacter'

open class AngryCat: ComicCharacter, GameCharacter {

           ^

note: protocol requires property 'fullName' with type 'String'; do you want to add a stub?

var fullName: String { get set }

    ^

note: protocol requires property 'score' with type 'UInt'; do you want to add a stub?

var score: UInt { get set }

    ^

note: protocol requires property 'x' with type 'UInt'; do you want to add a stub?

var x: UInt { get set }

    ^

note: protocol requires property 'y' with type 'UInt'; do you want to add a stub?

var y: UInt { get set }

    ^

note: protocol requires function 'drawAt(x:y:)' with type '(UInt, UInt) -> ()'; do you want to add a stub?

func drawAt(x: UInt, y: UInt)

     ^

note: protocol requires function 'moveTo(x:y:)' with type '(UInt, UInt) -> ()'; do you want to add a stub?

func moveTo(x: UInt, y: UInt)

     ^

note: protocol requires function 'intersects(character:)' with type '(GameCharacter) -> Bool'; do you want to add a stub?

func intersects(character: GameCharacter) -> Bool

     ^

We have to add the following lines to the body of the AngryCat class to implement the stored properties specified in the GameCharacter protocol. The code file for the sample is included in the swift_3_oop_chapter_05_08 folder:

    open var score: UInt = 0 
    open var fullName: String = String() 
    open var x: UInt = 0 
    open var y: UInt = 0 

In addition, we have to add the following lines to the body of the AngryCat class to implement the methods specified in the GameCharacter protocol. The code file for the sample is included in the swift_3_oop_chapter_05_08 folder:

    open func drawAt(x: UInt, y: UInt) { 
      self.x = x 
      self.y = y 
      print("Drawing AngryCat (fullName) at x: (x), y: (y)") 
    } 
 
    open func moveTo(x: UInt, y: UInt) { 
      self.x = y 
      self.y = y 
      print("Moving AngryCat (fullName) to x: (x), y: (y)") 
    } 
 
    open func intersects(character: GameCharacter) -> Bool { 
      return ((x == character.x) && (y == character.y)) 
    } 

Now, the AngryCat class declares the code for the three methods required to conform to the GameCharacter protocol: draw, move, and intersects. The code declares the three methods with the open access modifier. Finally, it is necessary to replace the previous initializer with a new one, which requires additional arguments and sets the initial values of the recently added stored properties. The following lines show the code for the new initializer. The code file for the sample is included in the swift_3_oop_chapter_05_08 folder:

    init (nickName: String, age: UInt, fullName: String, initialScore: 
    UInt, x: UInt, y: UInt) { 
      self.nickName = nickName 
      self.age = age 
      self.fullName = fullName 
      self.score = initialScore 
      self.x = x 
      self.y = y 
    } 

The new initializer assigns the value of the additional required fullName, initialScore, x, and y arguments to the fullName, score, x, and y properties. Thus, we will need to specify these additional arguments whenever we want to create an instance of the AngryCat class.

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

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