Ausgabe
Ich habe ein paar Beispiele gesehen, wie man :: equvalant in Scala schreibt, z. B. System.out::println an eine Funktion weitergibt, aber ich kann nicht herausfinden, wie man diese Vaadin Grid-Komponente in Scala schreibt:
Grid<Person> grid = new Grid<>(Person.class, false);
grid.addColumn(Person::getFirstName).setHeader("First name");
grid.addColumn(Person::getLastName).setHeader("Last name");
Hier sind die Get-Methoden reguläre Getter und keine statischen Methoden. Irgendeine Idee, wie dieser Code in Scala 2 (.12) geschrieben werden kann?
Bearbeiten: Der obige Java-Code ( grid.addColumn(..)
) ruft diese spezielle Methode auf:
public Column<T> addColumn(ValueProvider<T, ?> valueProvider) {
BiFunction<Renderer<T>, String, Column<T>> defaultFactory = getDefaultColumnFactory();
return addColumn(valueProvider, defaultFactory);
}
Lösung
Dies hängt von der Form der Methode und in einigen Fällen von der Version von Scala ab, die Sie verwenden. Scala 3 hat einige ziemlich bedeutende Änderungen an der Funktionsweise von Methoden vorgenommen, sodass einige der Syntax anders funktionieren.
Nehmen wir an, wir haben diese Signaturen.
def foo(n: Int): Int
def bar(a: Int, b: String): Int
def baz(): Int
def frobnicate: Int
Erstens, wenn Sie sich in Scala 3 befinden und die Methode obligatorische Argumente akzeptiert, können Sie einfach a verwenden .
und die Methode als erstklassiges Objekt erhalten. Also für jede der folgenden Methoden können Sie diesen Trick anwenden.
In diesem Fall myInstance.foo
ist eine Funktion von einem Argument und myInstance.bar
eine Funktion von zwei. Sie können diesen Trick nicht mit einer Funktion ohne Argumente verwenden, nicht einmal in Scala 3.
Wenn die Methode andererseits keine Argumente hat oder wenn Sie in Scala 2 arbeiten (das herauskam, bevor diese Syntax fertiggestellt wurde), können Sie eine Methode in ein Objekt umwandeln, indem Sie einen Unterstrich setzen (nicht in Klammern). Danach. Beispielsweise foo _
ist eine Funktion mit einem Argument in Scala 2 und 3. bar _
ist eine Funktion mit zwei Argumenten und baz _
eine Funktion mit null Argumenten. frobnicate _
ist eine Syntax, die früher in Scala 2 funktioniert hat, aber sie funktioniert nicht mehr für Funktionen mit Nullargumenten, die in Scala 3 ohne Klammern deklariert werden. In Scala 3 müssen Sie solche Funktionen in ein explizites Lambda einschließen.
Sie können (für Funktionen, die ein oder mehrere Argumente annehmen) auch explizit Unterstriche an den Argumentpositionen platzieren. Manchmal ist dies besser lesbar und erforderlich, wenn es mehrere Überladungen verschiedener Arten gibt. Sowohl in Scala 2 als auch in Scala 3 foo(_)
ist also eine Funktion aus einem Argument, während bar(_, _)
es eine Funktion aus zwei ist, und wir könnten sogar teilweise als oder anwenden bar
bar(0, _)
bar(_, "")
Zusammenfassend unter der Annahme der Signaturen, die oben in dieser Antwort aufgeführt sind:
Code | Scala 2-Verhalten | Scala 3-Verhalten |
---|---|---|
obj.foo |
Fehler | (Int) -> Int |
obj.bar |
Fehler | (Int, String) -> Int |
obj.baz |
Anrufebaz() |
Fehler |
obj.frobnicate |
Anrufefrobnicate |
Anrufefrobnicate |
obj.foo _ |
(Int) -> Int |
(Int) -> Int |
obj.bar _ |
(Int, String) -> Int |
(Int, String) -> Int |
obj.baz _ |
() -> Int |
() -> Int |
obj.frobnicate _ |
() -> Int |
Fehler |
obj.foo(_) |
(Int) -> Int |
(Int) -> Int |
obj.bar(_, _) |
(Int, String) -> Int |
(Int, String) -> Int |
() => obj.baz() |
() -> Int |
() -> Int |
() => obj.frobnicate |
() -> Int |
() -> Int |
Wenn Sie also maximal abwärtskompatibel sein wollen, dann setzen Sie am sichersten ein _
nach dem Funktionsnamen, wie in obj.foo _
. Dies funktioniert in jedem Fall, mit Ausnahme von Scala 3-Funktionen mit Nullargumenten, die ohne Klammern deklariert sind ( frobnicate
z. B. in unserem Beispiel). Für diese benötigen Sie ein explizites Lambda, as() => obj.frobnicate
Beantwortet von – Silvio Mayolo
Antwort geprüft von – Robin (FixError Admin)