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.
18.217.208.72