Table of contents
1.
Introduction
2.
What is Delegation?
3.
Types of Delegation
4.
Overriding a delegation-implemented interface member
5.
Property Delegation
5.1.
Using Lazy()
5.2.
Delegation.Observable()
6.
Application of Delegation
7.
Conclusion
8.
FAQs
9.
Key Takeaways
Last Updated: Mar 27, 2024

Kotlin Delegation

Author Rahul Sain
2 upvotes
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Delegation is preferable to inheritance in many situations. Delegation is well supported at the language level in Kotlin.

In this article, we will learn about Kotlin Delegation and the native support for the delegation pattern. But before jumping into this, we would strongly recommend learning about Kotlin Inheritance.

In the next section, we will now see the implementation of writing a delegate code.

What is Delegation?

Delegation is a technique for making a composition as powerful for reuse as an inheritance. A request is handled by two objects under delegation: a receiving object delegated activities to its delegate.

Delegation governs the transfer of power/authority from one object to another. When implemented, they can be utilized on static and changeable relations between classes and functions.

With delegation techniques, inheritance implementation in classes and functions can be changed, and object-oriented programming languages enable it intrinsically without any boilerplate code. It is accomplished in Kotlin with the use of the by keyword.

Kotlin allows the derived class to access all of an interface's implemented public methods via a specified object using this keyword or delegation mechanism.

Code:

interface BaseInterface {
    fun put() //here we are defining abstract method
 }
 
 class BaseClass(private val name: String) : BaseInterface {
    //overriding and implementing of the abstract method
    override fun put() {
        println(name)
    }
 }
 
 class DerivedClass(baseInterface: BaseInterface) :
    BaseInterface by baseInterface  // delegating the public method on the object baseInterface
 
 fun main() {
    val baseClass = BaseClass("Coding Ninjas")
    DerivedClass(baseClass).put() // prints Coding Ninjas :: accessing the put() method
 }

Output:

Coding Ninjas

In the example, we have one interface called BaseInterface, and its abstract method is called put(). This put() function is implemented in the BaseClass, and it is afterward used from DerivedClass using the by keyword.

Types of Delegation

  1. Explicit Delegation: All object-oriented languages support it, and it is accomplished by giving a delegate (the one to be implemented) object to the delegating object (the one that will implement the delegate object).
  2. Implicit Delegation: The delegation pattern needs language-level support.

Overriding a delegation-implemented interface member

Overrides function as expected: the compiler will utilize your override implementations rather than those in the delegate object. If you add the override fun put() print("Hello") to DerivedClass when put is called, the program will print Hello instead of CodingNinjas:

Code:

interface BaseInterface {
    fun put()
 }
 
 class BaseClass(private val name: String) : BaseInterface {
    override fun put() {
        println(name)
    }
 }
 
 class DerivedClass(baseInterface: BaseInterface) : BaseInterface by baseInterface {
    // overriding member of interface method
    override fun put() {
        println("Hello")
    }
 }
 
 fun main() {
    val baseClass = BaseClass("Coding Ninjas")
    DerivedClass(baseClass).put() // it will call override method of DerivedClass
    baseClass.put() // to call BaseClass method we have to use this
 }

Output:

Hello
Coding Ninjas

However, it should be noted that elements overwritten in this manner are not called from the delegate object's members, which can only access its implementations of the interface members.

Code:

interface BaseInterface {
    val no: Int
    fun put()
 }
 
 class BaseClass(private val name: String) : BaseInterface {
    override val no: Int = 2017
    override fun put() {
        println(name)
    }
 }
 
 class DerivedClass(baseInterface: BaseInterface) : BaseInterface by baseInterface {
    // the property is not accessible from baseInterface implementation of put
    override val no = 17
 }
 
 fun main() {
    val baseClass = BaseClass("Coding Ninjas")
    val derivedClass = DerivedClass(baseClass)
    derivedClass.put()
    println(derivedClass.no)
 }

Output:

Coding Ninjas
17

We get no variable value as 2017 only from baseClass object and not from derivedClass object.

Property Delegation

Delegation is the process of shifting responsibility to another class or method. When a property has been declared in several locations, we should use the same code to initialize it. Here we will use methods that Kotlin Library provides.

Using Lazy()

Lazy is a lambda function that accepts a property as an input and returns an instance of Lazy<T>, where <T> is the type of the properties it uses.

If you want to know more about Lambda Expressions, please reach out to this article for further information.

Code:

val name: String by lazy {
    "Coding Ninjas"
 }
 fun main() {
    println("$name has the best content")
 }

Output:

Coding Ninjas has the best content

We send a variable name to the Lazy function, which assigns the value to its object and returns it to the main() function.

Delegation.Observable()

Observable() accepts two arguments to initialize the object and returns the same to the calling function.

Code:

import kotlin.properties.Delegates

class Student {
   var name: String by Delegates.observable("Kurenai") { property, oldName, newName ->
       println("$oldName -> $newName")
   }
}

fun main() {
   val student = Student()
   student.name = "Sensei"
   student.name = "CodingNinjas"
}

Output:

Kurenai -> Sensei
Sensei -> CodingNinjas

Observable()'s first argument is the initial value of the property. The second argument is the callback function that will print oldName and newName. This will be called when we change the specified property's value.

Application of Delegation

Let's have a look at some everyday use cases for the delegation pattern now.

First, we can utilize the delegation pattern to use existing implementations to implement various interfaces.

Syntax:

class BaseClass : InterfaceOne by Interface1(), InterfaceTwo by Interface2()

Second, delegation can be used to improve an existing implementation. We have already covered this in the overriding delegation implemented method.

Lastly, It is a versatile, powerful, and mutable method.

Check out this article - Compile Time Polymorphism

Conclusion

Now, keep in mind that the delegate does not know the decorator. Finally, it's worth noting that with Kotlin, we can delegate not just to interfaces but also to single properties.

FAQs

  1. Why is delegation better than inheritance?
    The main benefit of delegation is runtime flexibility. At runtime, the delegate can be readily modified. However, unlike inheritance, most popular object-oriented languages may not directly enable delegation, and it does not allow for dynamic polymorphism.
     
  2. Does delegation promote code reuse?
    Delegation is a technique that encourages code reuse by allowing runtime function activation in the context of a given instance - regardless of the instance and function's hierarchical history.
     
  3. What's the difference between lazy and Lateinit?
    Lateinit can only be used with var properties, whereas lazy is always used with val properties. A lateinit property can be reinitialized as needed, whereas a lazy property can only be initialized once.

Key Takeaways

Cheers if you reached here!! 

The purpose of this article was to introduce you to the Kotlin Delegation, its various types, application, override methods, and understand the basic core concept about Delegation in Android Development.

If you want to learn more about Reflection in Kotlin, you can jump to this article which covers them in great detail.

However, learning never stops, and there is more to learn. So head over to our Android Development Course on the Coding Ninjas Website to dive deep into Android Development and build future applications. Till then, Happy Learning!

Live masterclass