How to add functionality to kotlin final class using delegation

Key takeaways:

  • In Kotlin, a final class cannot be subclassed, which restricts extending its functionality through inheritance.

  • Kotlin's delegation feature allows you to add functionality to a final class without subclassing, by passing method calls to another object that implements the required functionality.

  • We can create an interface for the desired functionality, then implement it in both the final class and a delegate class that enhances the behavior.

Kotlin, a modern programming language designed to run on the java virtual machine (JVM), has several features that enhance its usability and robustness. One such feature is the concept of final classes.

Final class

A final class cannot be subclassed in object-oriented programming. Hence we are unable to extend it with new functionality by creating a subclass. This can be useful for encapsulating behavior and ensuring certain implementations are not altered.

Because of this, we cannot explicitly add functionality to a final class. There are various ways to get through this limitation, though:

  • Using delegation

  • Using composition

  • Using a wrapper class

  • Using higher-order functions

In this Answer, we will explore the delegation feature to add functionality to a final class.

Kotlin delegation feature

A final class in Kotlin is specified by the final keyword in the class definition. Similar to other object-oriented programming languages, in Kotlin also, you cannot subclass a final class to add new functionality.

However, we can use Kotlin’s delegation feature to add functionality to a final class. Here’s an example:

interface MyInterface {
fun doSomething()
}
final class FinalClass : MyInterface {
override fun doSomething() {
println("Doing something in FinalClass")
}
}
class MyDelegate(val myFinalClass: FinalClass) : MyInterface by myFinalClass {
override fun doSomething() {
println("Doing something before FinalClass")
myFinalClass.doSomething()
println("Doing something after FinalClass")
}
}

Explanation

  • Lines 1-3: Creates an interface named MyInterface.

  • Lines 5-9: Defines a final class named FinalClass which implements the MyInterface interface, and provides an implementation for the doSomething() method that prints a message.

  • Lines 11-17: MyDelegate class delegates MyInterface implementation to a FinalClass object and adds before and after print statements to the doSomething() method.

We have a final class named as FinalClass that implements an interface MyInterface with a single method doSomething().

We also have a new class MyDelegate that implements the same interface and has an instance of FinalClass as a member variable. The important part is that we use the by keyword to assign myFinalClass responsibility for implementing myInterface.

This indicates that any doSomething() requests made to MyDelegate will be passed on to the FinalClass instance.To add some more functionality before and after calling FinalClass.doSomething(), MyDelegate overrides the doSomething() method.

This allows us to extend the behavior of FinalClass without subclassing it. To use this, we can create an instance of MyDelegate and call its doSomething() method:

fun main() {
val myDelegate = MyDelegate(MyFinalClass())
myDelegate.doSomething()
}

So in the main function, we created an instance of MyDelegate and called its doSomething() method.

Here is the full executable code :

interface MyInterface {
fun doSomething()
}
final class FinalClass : MyInterface {
override fun doSomething() {
println("Doing something in MyFinalClass")
}
}
class MyDelegate(val myFinalClass: FinalClass) : MyInterface by myFinalClass {
override fun doSomething() {
println("Doing something before MyFinalClass")
myFinalClass.doSomething()
println("Doing something after MyFinalClass")
}
}
fun main() {
val myDelegate = MyDelegate(FinalClass())
myDelegate.doSomething()
}

Unlock the power of Kotlin with our Kotlin Design Patterns and Best Practices course! Learn to leverage proven design patterns and best practices to enhance your development process, improve code quality, and build robust, maintainable applications.

Conclusion

Using delegation in Kotlin is a powerful strategy for enhancing the functionality of final classes, allowing developers to maintain encapsulation while still adding new behavior. By implementing interfaces and using the by keyword, we can create flexible and maintainable code without compromising the integrity of your final classes.

Frequently asked questions

Haven’t found what you were looking for? Contact Us


What is the opposite of final in Kotlin?

The opposite of final in Kotlin is open. An open class or member can be subclassed or overridden, allowing for extension and modification.


How do we add a function in Kotlin?

To add a function in Kotlin, we can define it using the fun keyword, followed by the function name and parameters. For example:

fun main() {
    println("Hello World!")
}

What is the by keyword in Kotlin?

The by keyword is used to delegate the implementation of an interface to another object.


Can we delegate functionality to a non-final class?

Yes, delegation can be used with any class, not just final classes.


Free Resources

Copyright ©2025 Educative, Inc. All rights reserved