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
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.
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