Inheritance vs Extension functions


We all know about inheritance which is there in the OOPs concept where one can extend a class and add functionality to it. In the new programming languages, there is something called as extension functions which can add a functionality to an existing class without extending it.
Sometimes we are confused about what to use when. To get help here, one needs to understand first what are these two and what are the benefits and limitations over the other. Once you understand the difference, it will be very easy to decide what to use.
Let's understand with code first what are both. I am going to explain using Kotlin language example but the concept is the same across all the languages.

Inheritance

Inheritance is nothing but extending a class and adding functionality to it. You can add properties (variables) as well as functions in the extending class. You can access the variables of extending (Base) class if they are not private (protected or internal or public) can override them if they are not final (open variables) or you can override the functions also.
  
open class Person(var firstName : String,
protected var lastName : String) {
open fun getFullDetails() : String {
return "$firstName $lastName"
}
}

class Student : Person {
var rollNumber = 0

constructor(firstName : String,
lastName: String,
rollNumber : Int)
: super (firstName, lastName){
this.rollNumber = rollNumber
}

override fun getFullDetails() : String {
return "$firstName $lastName with Roll number as $rollNumber"
}
}
And we can call it by using
  
var student = Student ("Suneet", "Agrawal", 12)
println(student.getFullDetails())
Here we added a property i.e. rollNumber and override the function.
Now let's have a look at almost similar functionality using Extension functions.

Extension Function

Extension functions are the functions where you add a functionality to an existing class by just adding a function without extending the class and this will be resolved statically and all the objects of that class can use it.
  
class Employee(var firstName : String, var lastName : String) {
}

fun Employee.getFullDetails() : String {
return "$firstName $lastName"
}
We have a similar kind of class which is non open (final class). we added a function getFullDetails as an extension function to the employee class and we call the above function as
  
var emp = Employee("Suneet", "Agrawal")
println(emp.getFullDetails())
Now that we understand what is extension functions and what is an inheritance, let try to find out the difference which will make our life really easy while choosing what to use when.

Merits of Extension functions

  • Can add functionality to a final class also. The class need not be a non-final (open) class.
  • Can add functionality without subclassing that means the object reference and the implementation can be of your base class.

Limitations of Extension functions

  • Can't access the protected variables/properties or functions of your base class.
  • Can't add any new variable/properties in your extension functions. You can add a property by just writing getter and setter but only without backing field. So basically you can't add a field in the base class.

Merits of Inheritance

  • Can add new properties, override functions (non-final) of the base class.
  • Can access all protected variables and functions of the base class.

Limitations of Inheritance

  • Can't extend a final class.

I hope this made clear on what are the merits and demerits of extension functions and inheritance. Please note that the extension functions are resolved statically.