2016-05-03 46 views
6

Załóżmy, że mam bardzo skomplikowaną specyfikację zdefiniowany jako interfejs:Kotlin delegacja do wyrażania zamiast stałym odniesieniem

interface Spec { 
    fun sayHello() 
} 

a standardowym realizacji:

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

Załóżmy teraz, że chcę, aby utworzyć klasa implementująca tę specyfikację i delegująca do implementacji, ale dokładny obiekt delegata jest modyfikowany przez cały okres istnienia obiektu. Oto przykład:

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

Problem z powyższym przykładzie jest to, że argument konstruktora target jest ustawiony jako obiekt delegata gdy konstruktor jest tzw. Dostęp do uczestnika jest wówczas możliwy bezpośrednio przez klasę zamiast wykonywania dostępu do właściwości. (Zostało to potwierdzone przez przeglądanie kodu bajtowego produkowanego przez Kotlin.)

Tak więc, nawet jeśli właściwość target została zmodyfikowana po skonstruowaniu klasy, delegat się nie zmienia.

Czy ktokolwiek może przedstawić metodę wykonywania tej delegacji w Kotlinie bez konieczności wypisywania każdej metody?

Idealne rozwiązanie umożliwiłoby również delegowanie do czegoś tak ogólnego, jak lambda lub inne wyrażenie, które byłoby oceniane i używane jako delegat, ilekroć delegat jest potrzebny przez cały okres istnienia obiektu.

Odpowiedz

6

W tej chwili nie ma sposobu, aby to zrobić. Zobacz Kotlin issue KT-5870

currenlty Kotlin ocenia wyrażenie dla delegata w klasie inicjatora

0

Możesz dodać poziom zadnie:

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 
    } 
} 

Niestety holder musi być parametrem konstruktora w celu wykorzystania z budową delegacji (tak jak w przypadku Kotlin v1.0), co komplikuje główny konstruktor.

+1

W tym przypadku musisz ręcznie przekazać wszystkie metody, których autor stara się uniknąć. – Michael

+0

@Michael tak, to prawda, jednak muszę tylko wykonać ręczną delegację tylko raz dla 'Posiadacza', po czym mogę go używać bez dodatkowego zestawu znaków – voddan

+0

Nie potrzebujesz do tego żadnych dodatkowych zajęć. Po prostu przekazuj wszystko od "Pochodnego". – Michael