Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delegate implementation to a property in Kotlin?

Tags:

kotlin

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?

like image 607
Marcin Kaczmarek Avatar asked Sep 05 '25 01:09

Marcin Kaczmarek


1 Answers

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.

like image 176
Alexander Udalov Avatar answered Sep 07 '25 04:09

Alexander Udalov