Caveats of Kotlin Delegation
We'll cover the following
Implementation caveat
In the example we’ve created so far, the Manager
may delegate calls to an instance of a JavaProgrammer
, but a reference to a Manager
may not be assigned to a reference of a JavaProgrammer
—that is, a Manager
may use a JavaProgrammer
, but a Manager
may not be used as a JavaProgrammer
. In other words, a Manager
has a JavaProgrammer
but is not a kind of JavaProgrammer
. Thus, delegation offers reuse without accidentally leading to substitutability as inheritance does.
However, there’s one small consequence of how Kotlin implements delegation. The delegating class implements the delegating interface, so a reference to the delegating class may be assigned to a reference of the delegating interface. Likewise, a reference to a delegating class may be passed to methods that expect a delegate interface. In other words, for example, the following isn’t valid:
val coder: JavaProgrammer = doe //ERROR: type mismatch
But the following is possible in Kotlin:
val employee: Worker = doe
This means a Manager
is a, or kind of a, Worker
. The true intention of delegation is for a Manager
to use a Worker
, but Kotlin’s delegate implementation introduces a side effect that a Manager
may be treated as a Worker
.
Delegating to a property caveat
Also, use caution when delegating to a property. We passed a parameter of type Worker
to the constructor of Manager
, using val
. In Prefer val over var, we discussed why we should prefer val
over var
. That recommendation is useful here too. If we decide to change the property that’s used as a delegate from val
to var
, a few consequences arise. Let’s see what those are with an example.
Here’s the full listing we’ll use for this example:
Get hands-on with 1200+ tech skills courses.