Declaring classes that inherit from another class

The following lines show the code for the Animal base class in Swift. The class header doesn't specify a base class, so this class will become our base class for the other classes. The code file for the sample is included in the swift_3_oop_chapter_04_01 folder:

    open class Animal { 
      open static var numberOfLegs: Int { 
        get { 
          return 0;           
        } 
      } 
      open static var averageNumberOfChildren: Int { 
        get { 
          return 0; 
        } 
      }     
      open static var abilityToFly: Bool { 
        get { 
            return false; 
        } 
      } 
     
      open var age: Int      
      init(age : Int) { 
        self.age = age 
        print("Animal created") 
      } 
     
      open static func printALeg() { 
        preconditionFailure("The pringALeg method must be overriden") 
      } 
     
      open func printLegs() { 
        for _ in 0..<type(of: self).numberOfLegs { 
          type(of: self).printALeg() 
        } 
        print(String())          
      } 
     
      open static func printAChild() { 
        preconditionFailure("The printChild method must be overriden") 
      } 
     
      open func printChildren() { 
        for _ in 0..<type(of: self).averageNumberOfChildren { 
          type(of: self).printAChild() 
        } 
        print(String()) 
      }      
      open func printAge() { 
        print("I am (age) years old.") 
      } 
    } 

The preceding class declares two read-only type computed properties and both return 0 as their value: numberOfLegs and averageNumberOfChildren. In addition, the class declares another read-only type computed property that returns false as its value: abilityToFly. We will be able to return different values for these properties in the different subclasses of Animal.

The initializer requires an age value to create an instance of the class and prints a message indicating that an animal is created. The class declares an age stored instance property. It defines the following three instance methods:

  • printAge: This displays the age based on the age value
  • printALeg: This uses preconditionFailure to indicate that each subclass must override this type method with a specific implementation that prints a single leg for the animal
  • printAChild: This uses preconditionFailure to indicate that each subclass must override this type method with a specific implementation that prints a single child for the animal

In addition, the class declares the following two type methods:

  • printLegs: This calls the printALeg method the number of times specified in the numberOfLegs type property. The method uses the type function with self as the value for the of argument to retrieve the runtime type as a value and access the type property for the specific type that we used to create the instance.
  • printChildren: This calls the printAChild method the number of times specified in the averageNumberOfChildren type property. As it happened in the pringLegs property, the code uses the type function with self as the value for the of argument to access the necessary type property.

If we execute the following line in the Playground after declaring the Animal class, Swift will generate a fatal error and indicate that the printAChild type method must be overridden, as shown in the subsequent screenshot. We will see similar error messages in the Swift REPL and in the Swift Sandbox. The code file for the sample is included in the swift_3_oop_chapter_04_02 folder:

    Animal.printAChild() 

Declaring classes that inherit from another class

We have to add additional functions to allow us to compare the ages of different Animal instances using operators. We will add the necessary code to perform this task later.

The following lines show the code for the Mammal class that inherits from Animal. Note the class keyword followed by the class name Mammal, a colon (:), and Animal, which is the superclass from which it inherits, in the class definition. The code file for the sample is included in the swift_3_oop_chapter_04_03 folder:

    open class Mammal: Animal { 
      open var isPregnant: Bool = false 
     
      private func initialize(isPregnant: Bool) { 
        self.isPregnant = isPregnant 
        print("Mammal created") 
      } 
     
      override init(age: Int) { 
        super.init(age: age) 
        initialize(isPregnant: false) 
      } 
     
      init(age: Int, isPregnant: Bool) { 
        super.init(age: age) 
        initialize(isPregnant: isPregnant) 
      } 
    }

The Mammal class inherits the members from the previously declared Animal class and adds a new Bool stored property initialized with the default false value. Note that this class declares two designated initializers. One of the initializers requires an age value to create an instance of the class, as it happened with the Animal initializer. The other initializer requires the age and isPregnant values. If we create an instance of this class with just one age argument, Swift will use the first initializer. If we create an instance of this class with two arguments--an Int value for age and a Bool value for isPregnant--Swift will use the second initializer. Thus, we have overloaded the initializer and provided two different initializers. Of course, we could also take advantage of optional parameters. However, in this case, we want to overload initializers.

The two initializers use the super keyword to call the inherited init method from the base class or superclass, that is, the init method defined in the Animal class. Once the superclass's initializer finishes its execution, each initializer calls the initialize private method that initializes the isPregnant stored property with the value received as an argument or the default false value in case it isn't specified.

Tip

We use super to reference the superclass.

One of the initializers uses the override keyword to override the initializer with the same declaration that is included in the superclass. We already had an initializer with an age argument of type Int in the Animal superclass. The other initializer doesn't require the override keyword because there is no initializer declared in the Animal superclass with the same arguments. The following lines create an instance of the Mammal class in the Playground using the designated initializer that just requires an age argument. The code file for the sample is included in the swift_3_oop_chapter_04_03 folder:

    var bat = Mammal(age: 3) 
    bat.printAge() 
    print(bat.isPregnant) 

The following lines show the results of the preceding lines. When the superclass initializer is executed, it prints Animal created, and after this happens, the initializer defined in the Mammal class prints Mammal created. The call to the printAge method defined in the Animal superclass prints the actual value of the age property in this instance of the Mammal class. Finally, a line prints the value of the isPregnant property that was initialized with false because we didn't specify a value for it:

    Animal created 
    Mammal created 
    I am 3 years old. 
    false 

The following lines create another instance of the Mammal class in the Playground using the initializer that requires two arguments: age and isPregnant. The code file for the sample is included in the swift_3_oop_chapter_04_03 folder:

    var cat = Mammal(age: 6, isPregnant: true) 
    cat.printAge() 
    print(cat.isPregnant) 

The following lines show the results of the preceding lines. The last line prints the value of the isPregnant property that was initialized with true in the initializer defined in the Mammal class:

    Animal created 
    Mammal created 
    I am 6 years old. 
    true  

The following screenshot shows the results of executing the preceding code in the Playground:

Declaring classes that inherit from another class

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

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