In this article, we will learn about abstract classes. We have learned in our previous article Inheritance that we can avoid duplication of the code by putting all the common code into the base class and extend that class as per the business needs. We can declare such a base class as an abstract class. Abstract classes can have concrete methods as well as methods with no implementation called abstract methods. So, the abstract class works as a template for its subclass where the implementation of the abstract method should be provided by its subclasses. Since abstract classes are incomplete, the instance of such classes cannot be created. We can access the concrete methods and properties of an abstract class via its subclasses.
There are a bunch of rules to follow while working with abstract classes.
- Abstract classes must be declared using the keyword abstract.
- If you want to have a method with no implementation, then you must declare it as abstract.
- Abstract classes are by default open so no need to mention it explicitly.
- The ultimate subclass of the abstract class must provide the implementation for all the abstract methods.
- Abstract class cannot be instantiated.
Abstract Class Example
abstract class Vehicle(name: String, modelNumber: String, color: String) {
abstract fun drive()
fun park() {
println("Let's park the vehicle")
}
}
class Car(val name: String, val modelNumber: String, val color: String) : Vehicle(name, modelNumber, color) {
override fun drive() {
println("Let's drive $name $modelNumber car of $color color")
}
}
fun main(args: Array<String>) {
val car = Car("BMW", "S3", "Red")
car.drive()
car.park()
}
As you might have observed, Vehicle class is marked as abstract, hence it can be extended without applying an open keyword. The subclass Car has overridden the abstract method drive(). The instance of the Vehicle cannot be created, so the instance of the Car class is created that can be used to invoke any members of the Vehicle class.
The abstract class might be extended by another abstract class then the ultimate subclass should provide the implementation for all the unimplemented abstract methods.
abstract class Vehicle(name: String, modelNumber: String, color: String) {
abstract fun drive()
abstract fun park()
}
abstract class Car(name: String, modelNumber: String, color: String) : Vehicle(name, modelNumber, color) {
init {
println("Let's wash $name $modelNumber car of $color color")
}
}
class BMW(val name: String, val modelNumber: String, val color: String) : Car(name, modelNumber, color) {
override fun drive() {
println("Let's drive $name $modelNumber car of $color color")
}
override fun park() {
println("Let's park $name $modelNumber car of $color color")
}
}
fun main(args: Array<String>) {
val bmw = BMW("BMW", "S3", "Red")
bmw.drive()
bmw.park()
}
Notice that the abstract class Car does not override the abstract method from its superclass Vehicle. The ultimate class BMW implements the method defined in the Vehicle as well as in the Car class. When the abstract class extends another abstract class then it takes all the abstract members of its parent class and the ultimate subclass will have to implement all the abstract methods.
The output of the above class is given below.
Output
Click on the next button to continue reading.
No responses yet