2016-10-26 27 views
5

Próbuję nauczyć się Kotlin i delegatów są zarówno interesujące i mylące. Mam sytuację, w której w klasie java wziąłbym konstruktora arg, utworzyłem Future (identyfikator reprezentuje zasób w innym systemie) i przechowuje Future jako zmienną instange. Wtedy „getXXX” nazwałbym Future.get()Kotlin delegujący do przyszłości

Oto próbka klasy java

public class Example { 


    private Future<Foo> foo; 

    public Example(String fooId) { 

     this.foo = supplyAsync(() -> httpClient.get(fooId)); 
    } 

    public Foo getFoo() { 
     return foo.get(); 
    } 
} 

ja nie dostarcza przykładu Kotlin, bo po prostu nie jestem pewien, jak go skonstruować.

Odpowiedz

6

można przetłumaczyć kod Java Kotlin w prosty sposób za pomocą custom property getters:

class Example(fooId: Int) { 
    private val fooFuture = supplyAsync { httpClient.get(fooId) } 

    val foo: Foo 
     get() = fooFuture.get() 
} 

Ale Kotlin ma mocniejszy koncepcję uogólniając zachowania nieruchomości - the property delegates:

class Example { 
    val foo: Foo by someDelegate 
} 

W tym przykładzie someDelegate jest obiektem, który definiuje zachowanie właściwości foo.

Choć Future<V> nie może być stosowany jako delegat z pudełka w Kotlin, można tworzyć własne delegatów własności poprzez wdrożenie getValue(thisRef, property) i (w przypadku zmiennych właściwości) setValue(thisRef, property, value) funkcje, co wyraźnie zapewniając kod wykonywany gdy nieruchomość jest odczytywany (i zapisywany, jeśli jest zmienny).

Te funkcje mogą być funkcjami składowymi dla klas projektów lub extension functions, co pasuje do przypadku z Future<V>. Zasadniczo, aby korzystać Future<V> jako delegat nieruchomości, należy zdefiniować funkcję getValue(thisRef, value) przedłużacza do niej, na przykład:

operator fun <V> Future<V>.getValue(thisRef: Any?, property: KProperty<*>) = get() 

Tutaj, wartość delegat zapewni nieruchomości będzie po prostu wzięte z Future::get zadzwoń, ale właściwa implementacja powinna prawdopodobnie zająć się odwołaniem i obsługą wyjątków. W tym celu można zawinąć obiekt Future<V> w klasę, która zdefiniuje również wartości/strategie zastępcze, a następnie użyć obiektów tej klasy w postaci by.

Następnie można użyć Future<V> obiektów jak delegatów na właściwościach:

class Example(fooId: Int) { 
    val foo: Foo by supplyAsync { Thread.sleep(2000); fooId } 
} 

fun main(args: Array<String>) { 
    val e = Example(123) 
    println(e.foo) 
} 
+0

Wariant 2 jest dokładnie to, czego szukam, bo muszę powtórzyć to wszędzie. Mam zamiar dać temu spin. –

+0

Ciekawe pytanie, które mam gdzie powinienem zdefiniować tę funkcję rozszerzenia. To znaczy, zdecydowanie nie należy do klasy danych. –

+0

@ChristianBongiorno, wiele projektów Kotlin zawiera pakiet 'Utils.kt' lub' utils', a rozszerzenia są często umieszczane tam, jeśli są używane w całym projekcie. Ale jeśli rozszerzenie jest używane lokalnie w jednym pliku, to wygląda dobrze, aby go tam umieścić i uczynić go "prywatnym". – hotkey

Powiązane problemy