Tuesday, September 25, 2018

Swift 4 Introduction Series 1.19 - Subclass and Inheritance

Subclass and Inheritance

In this chapter, we will be discussing the features of subclassing and inheritance. This is an important features that other data types such as structures do not have. After we defined structures, we can create instances of structures to be used as variables or constant. If we are to make changes, we have to change the definition of the original structure  or we have to define a different structure with a different name. However, if we use class and objects, we can reuse the code or modify the class without changing the main class. We can create subclass from the base class and make amendment or modification. This feature encourage re-use of the code and we can share the code to other programmer.


Before we start to perform subclass, lets define a base class using the example in the previous post.


class TransportVehicle {
   
   // Properties
   var speed:Double
   var maximumLoad:Double
   var numberOfPassenger:Int
   
   // Internal Used Properties
   var totalUseage: Int
   var preference: Int
   let maximumUsed = 50
   
   init() {
       self.speed = 1.0
       self.maximumLoad = 10.0
       self.numberOfPassenger = 1
       self.totalUseage = 0
       self.preference = 0
       
   }
   
   init(speed: Double, maximumLoad: Double, numberOfPassenger: Int) {
       self.speed = speed
       self.maximumLoad = maximumLoad
       self.numberOfPassenger = numberOfPassenger
       
       // User need to enter value but we still need to initialized them
       self.totalUseage = 0
       self.preference = 0
   }
   
   // Methods
   
   func displayInternalUsedNumber() {
       print("The internal used number is \(self.maximumUsed).")
   }
   
   func description () -> String {
       return "This is the base class"
   }
      
}


Next, we will define the sub class in the next section.


Define Subclass

To define subclass, we use the keyword class together with the name of base class. Base class is the class that do not base on other class.  The syntax is as follows:


class <subclass_name>:<baseclass_name> {


}


We can define a subclass as follows:


class LandTransportVehicle: TransportVehicle {
   
}


To implement the subclass, we create an instance as follow:


let landTransportVehicle1 = LandTransportVehicle()
We can use landTransportVehicle1 as the base class as shown below:


let landTransportVehicle1 = LandTransportVehicle()

landTransportVehicle1.maximumLoad
landTransportVehicle1.numberOfPassenger
landTransportVehicle1.speed
landTransportVehicle1.speed = 100.0
landTransportVehicle1.speed
landTransportVehicle1.displayInternalUsedNumber()
let descriptionString = landTransportVehicle1.description()



We can create an instance based on the subclass. The subclass inherits all the variables and function from the base class. The subclass can be empty and the instance still able to perform methods or access properties that is in the base class.


However, it is useless if we define a subclass without any modification. The purpose of subclassing is to add features and make modification that are specific to the subclass. Lets modify the subclass.


class LandTransportVehicle: TransportVehicle {
   
   // Property
   let modeOfTransport = "Land"
   let modeOfTransportCode = 1
   
}


The implementation is as follows:


let landTranportpVehicle2 = LandTransportVehicle()

landTranportpVehicle2.maximumLoad
landTranportpVehicle2.numberOfPassenger
landTranportpVehicle2.speed
landTranportpVehicle2.modeOfTransport



We have added 2 constant. These constant identify the instances as land transport vehicle.


Initialization

Using our previous example, we can dispense with initializer because the added constant is being initialized during definition. If we were to add some variable and we want programmer to input these variable, we can use an initializer.


Please checkout the subclass definition below:


class LandTransportVehicle: TransportVehicle {
   
   // Property
   let modeOfTransport = "Land"
   let modeOfTransportCode = 1
   
   var isThisTrain: Bool
   var poweredBy: String
   
   
   override init() {
       self.isThisTrain = false
       self.poweredBy = "Gas"
       
       super.init()
   }
   
   init(speed: Double, maximumLoad: Double, numberOfPassenger: Int, isThisTrain: Bool, poweredBy: String) {
       self.isThisTrain = isThisTrain
       self.poweredBy = poweredBy
       
       super.init()
       self.speed = speed
       self.maximumLoad = maximumLoad
       self.numberOfPassenger = numberOfPassenger
   }
}


As shown above, we have added 2 more variables; a boolean and a string. Since we did not initialized these 2 variables, we need to add the default initializer init().


Since we have init() in the parent class, we need to override them using the override keyword.  Next we need to set the default for the newly added variable. After that we need to call the init() from the parent class by using the super keyword. Super refers to the parent class.


For init(speed: Double, maximumLoad: Double, numberOfPassenger: Int, isThisTrain: Bool, poweredBy: String), override keyword is not necessary because it has five input, whereas init(speed: Double, maximumLoad: Double, numberOfPassenger: Int) only has 3 variables. As far as the system is concern, they are considered different initializer.


Override Method

Besides initializer, we can also override the methods. We cannot override properties by changing the values. We change the value using initializer or we can set the value directly.


To override function, we use the keyword override just before the function name. See example below:


override func description() -> String {
       return "This is a subclass that is based on transport vehicle base class. This class return "
   }


Implementation is as below:


let landTransportVehicle3 = LandTransportVehicle()

landTransportVehicle3.maximumLoad
let myString = landTransportVehicle3.description()



This is a very powerful feature as we can change the behavior of the function from the base class.


We can further create another subclass under land transport. In the follow example, we are creating 2 subclass, they are cars and bus.


class Cars: LandTransportVehicle {
   
   // properties
   var numberOfDoors = Int()
   var numberOfWheels = Int()
   
   override init() {
       self.numberOfDoors = 2
       self.numberOfWheels = 4
       
       super.init()
   }
   
   override func description() -> String {
       return "This is subclass cars parent is land transport vehicle > transport vehicle."
   }
   
}


class Bus: LandTransportVehicle {
   
   // Properties
   var numberOfDoors = Int()
   var numberOfWheels = Int()
   
   override init() {
       self.numberOfDoors = 2
       self.numberOfWheels = 6
       
       super.init()
   }
   
   override func description() -> String {
       return "This is subclass bus. Parent is land transport vehicle > transport vehicle."
   }
   
}


The implementation is as follows:


let car1 = Cars()
let car2 = Cars()
let bus1 = Bus()
let bus2 = Bus()

let carDesc1 = car1.description()
car1.numberOfWheels

car2.displayInternalUsedNumber()
car2.speed = 130

bus1.speed = 90
bus1.numberOfPassenger = 30

bus2.speed = 90
bus2.numberOfPassenger = 40


As we can see from the example above, additional properties and methods stack up down the class hierarchy. This save us time and preventing us from rewriting code that are similar. We can also delegate different team to work on different subclass.



****

No comments:

Post a Comment