The opposite of final in Kotlin is open. An open class or member can be subclassed or overridden, allowing for extension and modification.
Key takeaways:
In Kotlin, a
finalclass 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.
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.
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")}}
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.
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.
Haven’t found what you were looking for? Contact Us
Free Resources