2014-10-22 29 views
22

Betrachten Sie die folgende Java-Klasse:Lambda-Ausdrücke in Kotlin

public class SomeClass { 
    public interface Something { 
     void doSomething(); 
    } 

    public void call(Something something) {} 
} 

In Kotlin, kann ich einen Lambda-Ausdruck wie folgt verwenden:

SomeClass().call { 
    // do something 
} 

Aber wenn ich die folgende Methode in Kotlin definieren (mit die gleiche Schnittstelle):

fun call(something: Something) {} 

Dann ist dieser Aufruf:

call { 
    // do something 
} 

würde einen Typenkonfliktfehler erzeugen. Warum?

Antwort

25

Kotlin unterstützt nur SAM Konvertierungen für Java-Methoden, weil Kotlin selbst Funktionstypen hat. Normalerweise sollten Kotlin-Funktionen () -> Unit statt Something einnehmen. Wenn Sie es wirklich brauchen Something zu nehmen, können Sie eine SAM-Konstruktor verwenden:

call(Something { /* do something */ }) 

Alle SAM-Typ (Java-Schnittstelle mit einer abstrakten Methode) erhält automatisch einen solchen Konstruktor Funktion, die eine Lambda seine Instanz umwandelt.

+4

Diese Entscheidung sieht für mich komisch aus. Betrachte 'Liste <(T) -> Einheit>' vs 'Liste >'. Die zweite trägt viel mehr Informationen. Glücklicherweise gibt es einen Workaround: Wir können Java-Code frei in Kotlin-Projekten verwenden. – Yaroslav

+0

Obwohl diese Umgehungslösung nicht viel verwendet :( – Yaroslav

+3

Benannte Funktionstypen sind eine andere Geschichte. Und sie werden in der nächsten Version von Kotlin unterstützt –

8

Kotlin erfordert, dass der Anruf etwas von der Schnittstelle something übernimmt.

() -> Kotlin.Unit 

Erfüllt nicht die Typanforderung.

Sie können dies tun

call (object : Something { 
    override fun doSomething() { 
     println("Passing an interface to call in kotlin!") 
    } 
})