2010-07-13 5 views
6

Code implementieren Der Versuch, ähnlich wie in der übergeordneten Funktions Beispiel von http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6Scala Action/anonyme Funktion Typenkonflikt

val button = new JButton("test") 
button.addActionListener{ e:ActionEvent => println("test") } 
add(button) 

führt zu folgendem

error: type mismatch; 
found : (java.awt.event.ActionEvent) => Unit 
required: java.awt.event.ActionListener 
    button.addActionListener{ e:ActionEvent => println("test") } 
             ^

bei Dies gilt gefunden am wenigsten mit Scala-Compiler-Version 2.7.6.final auf meinem System. Ich bin in der Lage zu erreichen, was ich will in der Java-Stil Weise explizit implementieren einen anonymen ActionListener.

button.addActionListener(new ActionListener() { 
    def actionPerformed(e:ActionEvent) { println("test") } 
}) 

Soweit ich verstehe, sollte Scala der Lage sein, Ente-Eingabe zu verwenden, um diese explizite Implementierung von Action zu machen unnötig; Warum funktioniert es hier nicht? Ich habe zu diesem Zeitpunkt praktisch keine Erfahrung mit der Entchenung.

Antwort

11

Duck-Typisierung hat nichts damit zu tun, dass Ihr Code nicht funktioniert. Es ist , weil das Typensystem von Scala keine implizite Konvertierung zwischen dem Schnittstellentyp und dem Funktionstyp standardmäßig bereitstellt. Wenn die folgende implizite Konvertierung jedoch definiert ist, funktioniert Ihr Code ordnungsgemäß.

implicit def toActionListener(f: ActionEvent => Unit) = new ActionListener { 
    def actionPerformed(e: ActionEvent) { f(e) } 
} 

Diese implizite Konvertierung bietet Konvertierungen von (ActionEvent => Unit) zu ActionListner.

+1

Nicht als Fanboy, aber es ist erwähnenswert, dass sowohl Groovy als auch die verschiedenen Java-Schließvorschläge implizite Konvertierungen von entsprechenden Funktionstypen zu einzelnen Methodenschnittstellen enthalten. Dies ist sehr praktisch für Schnittstellen wie Runnable oder Comparable. In Scala müssen Sie diese Konvertierung entweder manuell durchführen oder sich auf pimped Bibliotheken verlassen, um dies zu tun. –

+1

@Dave Ja ... wenn der Typ nicht übereinstimmt, Auto-Cast. Ich denke, es sollte offensichtlich sein, warum Scala sich nicht so entschieden hat. –

+0

Oh, sicher. Dies ist nur sinnvoll für Groovy und Java, da sie keine guten Möglichkeiten zur Erweiterung vorhandener Bibliotheken enthalten. Daher benötigen sie diese automatische Konvertierung, um das Arbeiten mit Java-Legacy nicht schmerzhaft zu machen. Scala hat Zuhälter für Legacy-Bibliotheken, und neue Bibliotheken sollten (und werden) geschrieben werden, um Funktionsformen gegenüber Single-Method-Interfaces zu bevorzugen. –

4

Scala ist nicht duck-typed. Es hat optionale, explizite Struktur-Typisierung, aber das hat nichts damit zu tun, warum Ihr Code nicht funktioniert.

Ihr Code funktioniert nicht, da JButton.addActionListener ein ActionListener als sein Argument erwartet, keine Funktion. Selbst wenn Scala ducktypisch wäre, könnten Sie nicht einfach eine Funktion übergeben, da die gleichen Methoden, die auf einer ActionListener verfügbar sind, nicht auf einer Funktion verfügbar sind.

Beachten Sie, dass der Artikel sagt "Nehmen wir für einen glückseligen Moment, dass wir Swing neu schreiben könnten, um die Scala-Syntax voll auszunutzen", d. H. Der Artikel erhebt keinen Anspruch darauf, Ihnen tatsächlich funktionierenden Code zu zeigen.

Scala hat jedoch ein eigenes Swing-Paket (scala.swing), das Klassen enthält, die mehr "scalaish" zu verwenden sind als ihre Java-Entsprechungen.

+0

Ah, das Zitat aus dem Artikel ist in der Tat relevant. Ich hatte das Gefühl, eine Frage in der Öffentlichkeit zu stellen, war verpflichtet, einige grundlegende Leseverständnis Versagen von mir auszusetzen ... Dennoch ist Ihre Antwort informativ. Vielen Dank. – PeterT