Kotlin enables me to implement an interface by delegating to a primary constructor argument like so:
class Foo(xs : ArrayList<Int>) : List<Int> by xs { }
But this exhibits the backing implementer to the user. Delegating to an anonymous also seems to be ok:
class Foo() : List<Int> by ArrayList<Int>() { }
This hides the implementation details, but we loose access to features not provided by the interface, which in this case is mutability.
I would therefore like to delegate the implementation to a property that is not in the primary constructor. What I would like to have is similar to
class Foo() : List<Int> by xs {
val xs : List<Int> = ArrayList<Int>()
}
which doesn't compile.
Is it possible to have a property defined explicitly in the class body and still be able to delegate implementation to it?
This is not currently possible. The expression in the by
-clause is computed only once before the construction of the class, so you cannot reference symbols of that class.
There is a request in the issue tracker to allow this, although it's almost definitely not going to be supported in Kotlin 1.0.
One funny workaround that sometimes works is to make the property which you want to be a delegate, a constructor parameter with the default value instead. That way it'll be accessible both in the by
-clause and in the class body:
class Foo(val xs: List<Int> = ArrayList<Int>()) : List<Int> by xs {
fun bar() {
println(xs)
}
}
Keep in mind though that xs
in by xs
is still calculated only once here, so even if xs
is a var
property, only the default value provided in the constructor will be used. It's not a universal solution, but sometimes it can help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With