# OOPS with Kotlin

Kotlin is a modern, powerful, and developer-friendly language, especially for Android development. When compared with Java, it is more concise, readable, and better at handling null safety. Kotlin is a multi-paradigm language that supports both object-oriented programming (OOP) and functional programming features.

Let us look into the OOP side of Kotlin and how to implement the four great pillars of OOP

## Pillars of OOP

1. Encapsulation
    
2. Abstraction
    
3. Polymorphism
    
4. Inheritance
    

### Encapsulation

> the bundling of data (variables) and methods (functions) that operate on the data into a single unit. Restricts access to some attributes and exposes only necessary attributes for modification

Kotlin provides access modifiers like *private*, *public*, *internal*, and *protected* to control exposing access to attributes for modification.

```kotlin
class User {
    private var password: String = "secret" // password cannot be directly modified. 

    fun setPassword(newPassword: String) {
        // add any validation here if required, before making any modification
        password = newPassword
    }

    fun getPassword(): String {
       // add any validation here if required, before returning the password value
       return "****"  // Hiding actual password
    }
}
```

### Abstraction

> hides implementation details and only exposes relevant functionalities. This allows interacting with objects without needing to understand the complex inner workings.

In Kotlin, abstraction can be achieved in two ways. Abstract class and Interfaces.

#### Abstract Class

```kotlin
abstract class Vehicle {
    abstract fun start()  // No implementation
}

class Car : Vehicle() {
    override fun start() {
        println("Car is starting...")
    }
}
```

#### Interface

```kotlin
interface Clickable {
    fun click()
}

class Button : Clickable {
    override fun click() {
        println("Button clicked!")
    }
}
```

The major difference between an abstract class and an interface is that an abstract class can have both concrete methods and abstract methods, whereas interfaces cannot have method implementations. If you require to have functions that are not mandatory for the child class to implement or override, you can use an abstract class instead of an interface.

### Inheritance

> allows a class (child) to inherit the properties and behaviours of another class (parent)

In Kotlin, you can extend a class if it is ***open.***

```kotlin
open class Animal {
    fun eat() {
        println("munch munch munch...")
    }
}

class Dog : Animal() {
    fun bark() = println("Barking...")
}

fun main() {
    val dog = Dog()
    dog.eat()  // Inherited from Animal
    dog.bark()
}
```

One important thing to notice is that Kotlin **does not** support multiple inheritance by classes due to the complexity and ambiguity it can introduce. Read [Diamond Problem](https://en.wikipedia.org/wiki/Multiple_inheritance) if you want to learn more about the ambiguity. But in Kotlin, you can inherit multiple interfaces.

```kotlin
interface CookingSkill {
    fun makeBeefCurry()
    fun makeChickenTikka()
}

interface BakingSkill {
    fun makeCheeseCake()
}

class Chef : CookingSkill, BakingSkill {
    override fun makeBeefCurry() {
        TODO("Not yet implemented")
    }

    override fun makeChickenTikka() {
        TODO("Not yet implemented")
    }

    override fun makeTiramisu() {
        TODO("Not yet implemented")
    }

}
```

### Polymorphism

> allows a single function or method to have multiple behaviors depending on the object calling it.

Kotlin supports both method overriding and method overloading polymorphism.

#### Method Overriding

In Kotlin, to override a method, it is required to be explicitly mentioned as an ***open*** method.

```kotlin
open class Animal {
    open fun makeSound() {
        println("Making sound...")
    }
}

class Dog : Animal() {
    override fun makeSound() {
        println("Woof...")
    }
}

fun main() {
    val dog = Dog()
    dog.makeSound()
}
```

**Output:**

```bash
 Woof...
```

#### Method Overloading

```kotlin
class SumCalculations {
    fun add(a: Int, b: Int): Int {
        return a + b
    }

    fun add(a: Double, b: Double): Double {
        return a + b
    }
}

fun main() {
    val sumCalculations = SumCalculations()
    val firstOutput = sumCalculations.add(1,2) 
    val secondOutput = sumCalculations.add(1.1,2.2) 
}
```

---

Follow for more such posts on Kotlin and Android development.
