The following lines show the code for the complete Dog
class that inherits from DomesticMammal
. Note that the following code replaces the previous Dog
class that just declared an overridden type property. The code file for the sample is included in the swift_3_oop_chapter_04_07
folder:
open class Dog: DomesticMammal { open static override var numberOfLegs: Int { get { return 4; } } open static override var abilityToFly: Bool { get { return false; } } open var breed: String { get { return "Just a dog" } } open var breedFamily: String { get { return "Dog" } } private func initializeDog() { print("Dog created") } override init(age: Int, name: String, favoriteToy: String) { super.init(age: age, name: name, favoriteToy: favoriteToy) initializeDog() } override init(age: Int, isPregnant: Bool, name: String, favoriteToy: String) { super.init(age: age, isPregnant: isPregnant, name: name, favoriteToy: favoriteToy) initializeDog() } public final func printBreed() { print(breed) } public final func printBreedFamily() { print(breedFamily) } open func printBark(times: Int, otherDomesticMammal: DomesticMammal?, isAngry: Bool) { var bark = "(name)" if let unwrappedOtherDomesticMammal = otherDomesticMammal { bark += " to (unwrappedOtherDomesticMammal.name): " } else { bark += ": " } if isAngry { bark += "Grr " } for _ in 0 ..< times { bark += "Woof " } print(bark) } open func bark() { printBark(times: 1, otherDomesticMammal: nil, isAngry: false) } open func bark(times: Int) { printBark(times: times, otherDomesticMammal: nil, isAngry: false) } open func bark(times: Int, otherDomesticMammal: DomesticMammal) { printBark(times: times, otherDomesticMammal: herDomesticMammal, isAngry: false) } open func bark(times: Int, otherDomesticMammal: DomesticMammal, isAngry: Bool) { printBark(times: times, otherDomesticMammal: otherDomesticMammal, isAngry: isAngry) } open override func talk() { bark() } }
The Dog
class overrides the talk
method inherited from DomesticMammal
. As it happened with the overridden properties in other subclasses, we just add the override
keyword to the method declaration. The method doesn't invoke the method with the same name for its superclass, that is, we don't use the super
keyword to invoke the talk
method defined in DomesticMammal
. The talk
method in the Dog
class invokes the bark
method without parameters because dogs don't talk; they bark.
The bark
method is overloaded with four declarations with different arguments. The following lines show the four different declarations included within the class body:
open func bark() open func bark(times: Int) open func bark(times: Int, otherDomesticMammal: DomesticMammal) open func bark(times: Int, otherDomesticMammal: DomesticMammal, isAngry: Bool)
This way, we can call any of the defined bark
methods based on the provided arguments. The four methods end up invoking the printBark
open method with different default values for the arguments not provided in the call to bark
. The method builds and prints a message according to the specified number of times (times
), the optional destination domestic mammal (otherDomesticMammal
), and whether the dog is angry or not (isAngry
).
The Dog
class overrides the abilityToFly
type property with the static
keyword. This way, subclasses of dog won't be able to override this type property to return a different value because there is no known dog breed that can fly.
The class also declares two read-only computed properties: breed
and breedFamily
. We will override their getters in the subclasses of Dog
. The printBreed
instance method displays the value of the breed
computed property, and the printBreedFamily
instance method displays the value of the breedFamily
computed property.
We won't override these instance methods in the subclasses because we just need to override the values of the properties to achieve our goals; therefore, we declared both the methods with the final
keyword.
The following lines show the declarations of both methods with the final
keyword, which prevents the subclasses from overriding these methods:
public final func printBreed() public final func printBreedFamily()
If we call these instance methods from an instance of a subclass of Dog
, they will execute the code specified in the Dog
class, but the code will use the value of the properties overridden in the subclasses. Thus, we will see the messages displaying the values of the properties as defined in the subclasses.
We want to override both the printALeg
and printAChild
type methods inherited from Animal
in a subclass of Dog
. We declared both properties with the static
keyword, so we will only be able to override them if we replace this keyword with class
. The following lines show the code that replaces the declaration of both the properties in the Animal
class. Note that the rest of the code for the Animal
class remains without changes. The code file for the sample is included in the swift_3_oop_chapter_04_08
folder:
open class func printALeg() { preconditionFailure("The pringALeg method must be overriden") } open class func printAChild() { preconditionFailure("The printChild method must be overriden") }
The following lines show the code for the TerrierDog
class that inherits from Dog
. The code file for the sample is included in the swift_3_oop_chapter_04_08
folder:
open class TerrierDog: Dog {
open override class var averageNumberOfChildren: Int {
get {
return 5;
}
}
open override var breed: String {
get {
return "Terrier dog"
}
}
open override var breedFamily: String {
get {
return "Terrier"
}
}
private func initializeTerrierDog() {
print("TerrierDog created")
}
override init(age: Int, name: String, favoriteToy: String) {
super.init(age: age, name: name, favoriteToy: favoriteToy)
initializeTerrierDog()
}
override init(age: Int, isPregnant: Bool, name: String,
favoriteToy: String) {
super.init(age: age, isPregnant: isPregnant, name: name,
favoriteToy: favoriteToy)
initializeTerrierDog()
}
open override class func printALeg() {
print("|", terminator: String())
}
open override class func printAChild() {
// Print a dog's face emoji
print(String(UnicodeScalar(0x01f436)!), terminator: String())
}
}
As it happened in the other subclasses that we coded, we have more than one initializer defined for the class. In this case, one of the initializers requires age
, name
, and favoriteToy
to create an instance of the TerrierDog
class, and we also have an initializer that adds an isPregnant
argument. Both initializers invoke the superclass's initializer and then call the private initializeTerrierDog
method. This method prints a message indicating that a TerrierDog
class is created. The class overrides the getter methods to return "Terrier dog"
and "Terrier"
as the values for the breed
and breedFamily
computed properties that were defined in the superclass and overridden in this class.
In addition, the class overrides the getter method for the averageNumberOfChildren
type property. However, in this case, the overridden type property declaration uses the class
keyword because we want to enable the subclasses of TerrierDog
to be able to override this type property. The Terrier
family is huge, and some of the members of this family have a different average number of children.
The class also overrides both the printALeg
and printAChild
type methods inherited from Animal
. The printALeg
method prints a pipe symbol (|
), and the printAChild
method prints a dog's face emoji.
18.119.102.160