Делегация Котлина выражает вместо фиксированной ссылки

Предположим, что у меня очень сложная спецификация, определенная как интерфейс:

interface Spec { fun sayHello() } 

И стандартная реализация:

 class Impl(private val msg: String) : Spec { override fun sayHello() { println(msg) } } 

Предположим теперь, что я хочу создать класс, который реализует эту спецификацию и делегирует ее реализации, но точный объект-делегат изменен на протяжении всего жизненного цикла объекта. Вот пример:

 class Derived(var target: Spec) : Spec by target 

Проблема с приведенным выше примером заключается в том, что target аргумент конструктора задается как объект-делегат при вызове конструктора. Затем делегат получает доступ непосредственно к классу, а не к доступу к собственности. (Это подтверждается просмотром байт-кода, выпущенного Котлином.)

Таким образом, даже если target изменяется после создания класса, делегат не изменяется.

Может ли кто-нибудь предоставить метод для выполнения этой делегации в Котлине без необходимости выписывать каждый метод?

Идеальное решение также позволит делегировать что-то общее, как лямбда или другое выражение, которое будет оцениваться и использоваться в качестве делегата всякий раз, когда делегат необходим на протяжении всего жизненного цикла объекта.

Сейчас нет способа сделать это. См. Вопрос Kotlin KT-5870

Currenlty Kotlin оценивает выражение для делегата в инициализаторе класса

Вы можете добавить уровень косвенности:

 class Holder(var impl: Spec) : Spec { override fun sayHello() = impl.sayHello() } class Derived(target: Spec, private val holder: Holder = Holder(target)) : Spec by holder { fun changeTarget(newTarget: Spec) { holder.impl = newTarget } } 

К сожалению, holder должен быть параметром конструктора для использования с конструкцией делегирования (как для Kotlin v1.0), поэтому он усложняет основной конструктор.