Idiomatic Kotlin: Class Delegates
This article is a part of the Idiomatic Kotlin series. The complete list is at the bottom of the article. I have also written an article before regarding class delegation and if you are interested, you can go check it out.
In this article, we will be exploring class delegation in Kotlin.
What is Class Delegation?
Class delegation builds up on the generic delegation idea wherein a responsibility is being passed to another entity. Delegation pattern is one of the design patterns in object oriented paradigm and it uses composition to achieve it. The basic idea of class delegation is that, you can implement an interface by owning an object that implements the same interface and delegate the responsibility to that object.
Delegation pattern involves a lot of boilerplate code. Fortunately for us, Kotlin has first-class support for delegation as a language feature.
Motivation
There is a long-standing debate about whether to prefer composition vs. inheritance. Some of the compelling arguments are as follows:
- Inheritance breaks encapsulation — this one is best described by Joshua Bloch in his book Effective Java. Basically, some classes are not “inheritance-ready” and inheriting them requires you to look at the implementation details, which breaks the encapsulation.
- Inheritance is fragile — changes in the superclass interface will propagate to all the subclasses down the hierarchy.
- Design perspective — it is easier to think of objects as a set of components combined rather than finding their shared properties.
- Lazy — inheritance does not allow for lazy loading of super class.
How to delegate classes?
When delegating classes, it is mandatory that the delegate and the class that performs delegation both inherit the same interface. Then the magic keyword is by
. Let us take a look at an example.
The Huskar
class both implements AttackType
and HeroType
interfaces by delegating them to instances of Ranged
and Strength
classes.
Class delegation under the hood
The above class when decompiled will look like this
The Java implementation is not at all surprising. It is what we have been doing all along. Create read-only fields, generate the interface methods, and delegate the call to the field objects. Still the same delegation pattern we all love (or hate).
Check out the other articles in the idiomatic kotlin series. The sample source code for each article can be found here in Github.
- Extension Functions
- Sealed Classes
- Infix Functions
- Class Delegation
- Local functions
- Object and Singleton
- Sequences
- Lambdas and SAM constructors
- Lambdas with Receiver and DSL
- Elvis operator
- Property Delegates and Lazy
- Higher-order functions and Function Types
- Inline functions
- Lambdas and Control Flows
- Reified Parameters
- Noinline and Crossinline
- Variance
- Annotations and Reflection
- Annotation Processor and Code Generation