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
Encapsulation
Abstraction
Polymorphism
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.
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
abstract class Vehicle {
abstract fun start() // No implementation
}
class Car : Vehicle() {
override fun start() {
println("Car is starting...")
}
}
Interface
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.
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 if you want to learn more about the ambiguity. But in Kotlin, you can inherit multiple interfaces.
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.
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:
Woof...
Method Overloading
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.



