Scala und Java Generics - Extrahieren und Zurückgeben verschachtelter Typen

9

Java-Generics können den Typ der generischen Typparameter basierend auf dem Rückgabetyp von Ausdrücken ableiten. Berücksichtigen Sie Folgendes:

%Vor%

Wir können es so nennen:

%Vor%

Dies wird kompilieren, aber ein RuntimeException werfen, wenn es aufgerufen wird, da es versuchen wird, Map in ein String zu konvertieren, aber fehlschlägt. Aber der Punkt ist, dass Java den Wert von <T> basierend auf dem erwarteten resultierenden Typ auf der Callsite abgeleitet hat.

Das können wir auch in Scala mit:

machen %Vor%

So weit, so gut.

Java kann auch Typargumente aus verschachtelten Definitionen ableiten und diese zurückgeben (d. h. wir müssen das Ergebnis nicht tatsächlich einem Typ zuweisen, um es wie oben zu verwenden, bevor es verwendet wird; Java weiß, was es bereits ist.)

Eine einfache Klasse, die das zeigt:

%Vor%

In Scala verursacht diese Klasse jedoch Probleme. Die REPL:

%Vor%

Die beiden Aufrufe von put() geben einen Wert für den Parameter V type an, mit dem sie arbeiten können, aber sobald der Parameter V aus der Vererbung des Parameters K extrahiert werden muss Nervenzusammenbruch. Der Java-Code hat kein solches Problem.

Die einzige Möglichkeit, Scala nicht zu beschweren, ist, die Typen explizit zu definieren:

%Vor%

(Für etwas Einfaches und Konstruktives wie oben, ist es marginal in Ordnung (verletzt DRY), aber für etwas, das involvierter ist, wie die Stanford Core NLP API, wo man so etwas machen muss:

%Vor%

Das manuelle Nachschlagen der geschachtelten Typen, so dass Sie sie hinzufügen können, ist ziemlich schmerzhaft.)

Die Frage (n):

Gibt es eine Möglichkeit, dies zum Laufen zu bringen, ohne die Typparameter so ausführlich angeben zu müssen? Noch wichtiger, warum ist das ein Problem von Anfang an? Wie kann Java das Typargument ableiten, wenn Scala nicht ist?

EDIT 1 : Der meiste Code, der das Stanford-Core-NLP-Problem demonstriert, wurde entfernt und durch ein allgemeines Beispiel für den Unterschied in Scala / Java-Generics ersetzt, der das Problem veranschaulicht.

    
DK_ 11.02.2013, 15:54
quelle

1 Antwort

3

Ich kann Ihnen nicht genau sagen, warum Scala die Java-Typparameter nicht ableiten kann, aber ich kann Ihnen zumindest zeigen, wie Sie die Typparameter in Java deklarieren, damit Scala auf sie schließen kann:

%Vor%

Ich denke, der entscheidende Punkt hier ist, dass Sie den K -Typ-Parameter überhaupt nicht benötigen - ein Parameter vom Typ "Wildcart", ? extends Key<V> , wird Ihnen die gleiche Funktionalität geben. Dies funktioniert dann glücklicherweise von Scala, ohne irgendwelche Typparameter angeben zu müssen:

%Vor%

BEARBEITEN:

Hier ist das Beste, was ich für einen Workaround tun könnte. Es erfordert höherwertige Typen und eine Besetzung. Nicht sicher, dass ich erklären kann, warum das kompiliert, aber die andere Version nicht. ; -)

%Vor%     
Steve 12.02.2013 19:04
quelle