Introduction
In this blog I will explain the delegates in Kotlin in simple terms.
Before jumping to the topic, let’s understand the true English meaning of Delegation.
Delegation — Passing responsibility to someone else.
In programming we can see delegation as passing the work of one class/property to another class/property.
Delegation
Let’s start with the simple example.
Say we create an interface Action that contains two functions (eat and breathe):
interface Action {
fun eat()
fun breathe()
}
Now, let’s say we create a class Animal that implements the interface Action (assuming each animal in the world can eat and breathe)
class Animal(val name: String): Action {
override fun eat() {
println("$name eats")
}
override fun breathe() {
println("$name breathes")
}
}
Now we create a class Bird, and we know that bird is an animal that can eat and breathe, but bird can also fly, so we have two ways:
Bird class can also implement Action (eat and breathe) and also add fly function.
Or, since we know bird also do all the action(eat and breathe) that are already implemented by Animal class, we can just pass the responsibility to implementing Action to Animal, as it is already implemented by Animal.
This is delegation, passing the responsibility (or delegating) to Animal class.
We will use “by” keyword from Kotlin syntax for achieving the same.
class Bird(private val name: String): Action by Animal(name) {
fun fly() {
println("$name flies")
}
}
Let’s take one more example, we have aquatic animals that can swim, eat, breathe but cannot fly. We will delegate the Action properties to Animal class and only add swim method.
class AquaticAnimal(private val name: String): Action by Animal(name) {
fun swim() {
println("$name swims")
}
}
Now to use it we can do:
fun main() {
/**
* Delegation
*/
val parrot = Bird("Parrot")
parrot.eat()
parrot.breathe()
parrot.fly()
val fish = AquaticAnimal("Fish")
fish.eat()
fish.breathe()
fish.swim()
}
This is also known as Delegation pattern in software engineering.
Property Delegation
Till now we have seen how we delegates the one class to another.
In Kotlin we have one more type of delegation, i.e, property delegation.
We can delegate the setter and getter of some property to another class.
Let’s understand with an example:
/**
* Property Delegation: Delegate Property (pass responsibility of getter and setter) to other class
*/
class Name {
var firstName: String by NameDelegate()
var lastName: String by NameDelegate()
constructor(firstName: String, lastName: String) {
this.firstName = firstName
this.lastName = lastName
}
}
class NameDelegate {
private lateinit var name: String
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return name
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
if(value.isNotEmpty() && value.all { it.isLetter() }) {
name = value
} else {
throw IllegalArgumentException("Name must not be empty and should only contains letter")
}
}
}
fun main() {
/**
* Property Delegation
*/
val name = Name("Khush", "Panchal") // If use "Khush1", "Khu sh", will get an exception.
val firstName = name.firstName
val lastName = name.lastName
println("$firstName $lastName")
}
Let’s dive into the above example to understand the property delegation:
Say we create a class Name, which has two variables, firstName and lastName. As this class takes just a string as a type of variables and not validating the name entered, we can pass the responsibility of validation to another class.
In above example, we have created a class NameDelegate and write two operator function getValue and setValue.
Kotlin Syntax: We can use predefined operator function and write our own logic
And to delegate the properties we have to use “by” keyword and in this way all the get and set call on variable name will go through operator function of NameDelegate class. Here while setting any name we throw the exception if the name contains anything else then letters.
Kotlin standard library also provides few useful delegates like lazy, observable, storing properties in map. [Check out for more details]
Source code: Github
Contact Me:
Happy Coding ✌️