Inheritance
Inheritance is a fundamental object-oriented programming (OOP) concept that allows a class (subclass or derived class) to inherit all the properties and behaviors of another class (superclass or base class).
classes are final by default, meaning they cannot be subclassed. To allow a class to be subclassed, use the open keyword.
Syntax for Inheriting: To inherit from a class, use the colon : followed by the name of the superclass.
class Subclass : Superclass() {
// class definition
}
Base Class (Superclass): The class that is being inherited is called the superclass or base class.
open class Animal {
// class definition
}
Derived Class (Subclass): The class that inherits from another class is called the subclass or derived class.
class Dog : Animal() {
// class definition
}
Example of Inheriting property and methods from base class:
// Base class
open class Animal(val name: String) {
// Property and method of the base class
fun makeSound() {
println("$name makes a sound")
}
}
// Derived class inheriting from the base class
class Dog(name: String, val breed: String) : Animal(name) {
// Additional property and method of the derived class
fun bark() {
println("$name barks loudly")
}
}
fun main() {
// Creating an instance of the derived class
val myDog = Dog("Buddy", "Labrador")
// Accessing properties and methods from the base class
println("Name: ${myDog.name}")
myDog.makeSound()
// Accessing properties and methods from the derived class
println("Breed: ${myDog.breed}")
myDog.bark()
}
Explanation
Dog
is a derived class that inherits from Animal
using : Animal(name)
. Both base class (Animal
) and derived class (Dog
) properties and methods are accessed by Dog instance.
The : Animal(name)
syntax in the derived class declaration ensures that the base class constructor is called when creating an instance of the derived class.
When you run this program, you should see the following output:
Name: Buddy
Buddy makes a sound
Breed: Labrador
Buddy barks loudly
Overriding Member functions and properties:
If Base class and derived class contains function and properties with same name, then we can override the member function of Base class in derived class using override keyword. we also need to mark the function and properties of the base class with open keyword
// Base class
open class Vehicle {
open fun start() {
println("Vehicle is starting")
}
open val fuelType: String = "Petrol"
}
// Derived class
class ElectricCar : Vehicle() {
override fun start() {
println("Electric car is starting")
}
override val fuelType: String
get() = "Electricity"
}
The Vehicle
class is a base class with a method start
and a property fuelType
. The ElectricCar
class is a derived class that inherits from Vehicle
and overrides the start
method and the fuelType
property.
fun main() {
// Creating instances of base and derived classes
val genericVehicle: Vehicle = Vehicle()
val electricCar: Vehicle = ElectricCar()
// Calling overridden methods
genericVehicle.start() // Output: Vehicle is starting
electricCar.start() // Output: Electric car is starting
// Accessing overridden properties
println("Generic Vehicle Fuel Type: ${genericVehicle.fuelType}") // Output: Generic Vehicle Fuel Type: Petrol
println("Electric Car Fuel Type: ${electricCar.fuelType}") // Output: Electric Car Fuel Type: Electricity
}
Explanation:
When genericVehicle.start()
is called, the compiler looks at the type of genericVehicle
at compile-time, which is Vehicle
. It then knows to call the start
method defined in the Vehicle
class.
when electricCar.start()
is called, the compiler looks at the type of electricCar
at compile-time, which is still Vehicle
(due to the declared type). However, at runtime, the actual type of the object is ElectricCar
. Therefore, the overridden start
method in the ElectricCar
class is called. (Output: Electric car is starting
)
Advantage of using Inheritance in kotlin:
- Code Reusability: Inheritance allows you to reuse code from an existing class. Instead of writing the same code multiple times for different classes, you can create a base class with common attributes and methods. Subclasses can then inherit these features, reducing redundancy and making the code more maintainable.
- Polymorphism: Inheritance supports polymorphism, allowing objects of a derived class to be used wherever objects of the base class are expected.
- Base Class Abstraction: A base class provides an abstraction of common properties and behaviors, serving as a blueprint for derived classes to follow.
- Extensibility: it is easy to add new features or change existing ones without messing up the original code. It’s like building on top of what you already have.
- Maintenance and Updates: It is easy to change something, it’s easier to find and update. If you fix or improve the basic template (base class), all the similar things (subclasses) automatically get the update.
Disadvantage of using Inheritance in kotlin:
- Increased Code Complexity: If you have lots of classes arranged in a deep hierarchy, using inheritance can make code more complicated.
- Tight Connection Between Classes: Inheritance creates a strong link between a main class (superclass) and its related classes (subclasses). This close connection can make it hard to make changes to the main class without affecting the others.
- Issues with Changing and Adding Features: When you make changes to the main class, it can cause problems throughout the whole hierarchy of classes. This can be a headache when you want to add new features or modify existing ones.