OOP Implementation In Kotlin

Like other OOP languages, we can implement all the features of OOP in Kotlin too. In this article, I am going to show how to implement all the features.These features are,

  • Class
  • Object
  • Inheritance
  • Polymorphism
  • Abstraction
  • Interface
Class & Object

Kindly go through my article, "Understanding Classes in Kotlin" to learn how to implement classes and objects in Kotlin.

Inheritance

For inheritance also, refer to my previous article - Code Reusability In Kotlin

Polymorphism

When any variable, function, or object has more than one forms, this concept is known as polymorphism. There are two types of polymorphism.

Kotlin

Static polymorphism is also known as compile time polymorphism. Let us understand it by method overloading.

Method Overloading

When methods have the same name but different signature, which are used to performing different kinds of operations.

  1. class MethodOverloading{  
  2.     fun area(a:Int):Int{  
  3.         return a*a  
  4.     }  
  5.     fun area(length:Int,height:Int):Int{  
  6.         return length*height  
  7.     }  
  8.     fun area(base:Float,height:Float):Float{  
  9.         return (base*height)/2  
  10.     }  
  11. }  
  12. fun main(args:Array<String>){  
  13.     var obj=MethodOverloading()  
  14.     println("Area of Square="+obj.area(5))  
  15.     println("Area of Rectangle="+obj.area(5,4))  
  16.     println("Area of Triangle="+obj.area(10.05f,5.5f))  
  17. }  
  18. /*output: 
  19. Area of Square=25 
  20. Area of Rectangle=20 
  21. Area of Triangle=27.6375 
  22. */    
Explanation

In the above example, all these three methods are having the same name but they are used to calculate the areas of a square, a rectangle, and a triangle respectively.

Operator Overloading

There are two categories to perform operator overloading – 1. Unary Operator Overloading and 2. Binary Operator Overloading. Kotlin provides the specific name of functions associated with the operators to overload them, like – dec, unaryPlus, plus, plusAssign, div, divAssign, and equals etc. Let’s see how you can perform these operations.

Unary Operator Overloading

You can use Unary increment and decrement operators in your own way by overloading them. Even those will have their same precedence.

Example

Let‘s understand unary decrement operator overloading with an example.

  1. data class Unary(var number : Int)  
  2. {  
  3.    operator fun  dec( ) : Unary{  
  4.        var newnum=this.number - 1  
  5.        return Unary(newnum)  
  6.    }  
  7.   
  8. }  
  9. fun main(args:Array<String>){  
  10.     var unaryobj=Unary(5)  
  11.      println(--unaryobj)  
  12. }  
  13. //Unary(number=4)  
Binary Operator Overloading

Binary operator overloading is similar to Unary Operator overloading; the only difference is that the binary operators require at least two operands whereas the unary operators require only one.

Example

Here is an example of Binary Operator overloading to add a string with a number.

  1. data class BinaryOperatorOverloading(var result:String){  
  2.     operator fun plus(number:Long):BinaryOperatorOverloading{  
  3.         return BinaryOperatorOverloading(result+number)  
  4.            }  
  5. }  
  6. fun main(args:Array<String>){  
  7. var boolobj=BinaryOperatorOverloading("WhatsApp No.:")  
  8.     println(boolobj.plus(8882265032))  
  9. }  
  10. //output:  
  11. //BinaryOperatorOverloading(result=WhatsApp No.:8882265032)  

In the above example, you can see ‘BinaryOperatorOverloading’ class which has a function ‘plus’ being defined as how this function will work.

Dynamic Polymorphism

This is also known as runtime polymorphism or late binding – this is used to decide which block of code of a function will be executed after the function call at the runtime of the program. Let us see with an example.

  1. open class Car(var speed:Int){  
  2.  open  fun show(){  
  3.         println("car is running on $speed km/hrs")  
  4.     }  
  5. }  
  6. class Mercedize(var mspeed:Int) : Car(mspeed){  
  7.     override fun show(){  
  8.         println("Mercedize is running on $mspeed km/hrs")  
  9.     }  
  10. }  
  11. fun main(args:Array<String>){  
  12.     var newcar=Mercedize(150);  
  13.     println(newcar.show())  
  14. }  
  15. /* output : 
  16. Mercedize is running on 150 km/hrs 
  17. */  

Abstraction

Abstraction is a technique to show the most important information and hiding less important information in order to reducing the complexity. We can use Abstract classes and interface too for this purpose.

Abstract class

It has the abstract and concurrent methods. An abstract class can’t initiate but it can be inherited. You can create and use abstract class in following way.

  1. abstract class Policy{  
  2.     abstract fun dept()  
  3.     fun operations(){  
  4.       println("It softwares")  
  5.     }  
  6. }  
  7. class Company:Policy(){  
  8.     override fun dept() {  
  9.        println("Departmental Polycies")  
  10.     }  
  11. }  
  12. fun main(args:Array<String>){  
  13.     var com=Company()  
  14.     com.operations()  
  15.     com.dept()  
  16.     }  
  17. /* Output:  It softwares 
  18. Departmental Polycies   */  
Interface

Interface contains method without definition (abstract methods). You have to implement these methods of the interface in class. Interface in Kotlin is

  1. interface Furniture{  
  2.     fun show()  
  3.     fun message(){  
  4.         println("This is concurrent method message")  
  5.     }  
  6. }  
  7. class Chair : Furniture{  
  8.     override fun show() {  
  9.             println("This is show method message")  
  10.             }  
  11. }  
  12. fun main(args:Array<String>){  
  13.     var wheel=Chair()  
  14.     wheel.message()  
  15.     wheel.show()  
  16. }  
  17. /* 
  18. Output: 
  19. This is concurrent method message 
  20. This is show method message 
  21. */  

In this example, you can judge that the working of interface is very close to abstract classes. The only difference between abstract class and interface is that interface does not maintain the state while an abstract class maintains. It means that you cannot initialize a variable in an interface.