2010-07-13 19 views
6

El intento de poner en práctica un código similar a la encontrada en el ejemplo de orden superior-función de http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6Scala ActionListener/Tipo de función anónima desajuste

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

conduce a la siguiente

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

Esto es cierto a al menos con el compilador Scala versión 2.7.6.final en mi sistema. Puedo lograr lo que quiero en la forma del estilo Java de implementar explícitamente un ActionListener anónimo.

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

Por lo que yo entiendo, Scala debe ser capaz de utilizar de pato a escribir para hacer esta implementación explícita de ActionListener innecesaria; Entonces, ¿por qué no funciona aquí? En este punto, casi no tengo ninguna experiencia práctica de tipado de patos.

Respuesta

11

Duck-typing no tiene nada que ver con la razón por la que su código no funciona. Es porque el sistema de tipos de Scala no proporciona una conversión implícita entre el tipo de interfaz y el tipo de función de forma predeterminada. Sin embargo, si se define la siguiente conversión implícita, su código funciona correctamente.

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

Esta conversión implícita proporciona conversiones desde (ActionEvent => Unit) a ActionListner.

+1

No como fanboyismo, pero vale la pena señalar que tanto Groovy como las diversas propuestas de cierre de Java incluyeron conversiones implícitas de tipos de funciones apropiadas a interfaces de método único. Esto es muy conveniente para interfaces como Runnable o Comparable. En Scala, o necesita hacer esta conversión a mano, o recurrir a bibliotecas de pimped para hacerlo. –

+1

@Dave Sí ... si el tipo no coincide, autoinélelo. Creo que debería ser obvio por qué Scala no eligió de esta manera. –

+0

Oh, ciertamente. Solo tiene sentido para Groovy y Java porque no incluyen ninguna buena forma de extender las bibliotecas existentes, por lo que necesitan esta conversión automática para que el trabajo con Java heredado no sea doloroso. Scala tiene proxenetas para bibliotecas heredadas, y las nuevas bibliotecas deberían estar (y están siendo) escritas para favorecer formas funcionales sobre interfaces de método único. –

4

Scala no está escrito en pato. Tiene tipado estructural explícito opcional, pero eso no tiene nada que ver con por qué tu código no funciona.

Su código no funciona, porque JButton.addActionListener espera un ActionListener como argumento, no como una función. Incluso si scala tuviera un formato duck, no podría simplemente pasar una función porque los mismos métodos disponibles en un ActionListener no están disponibles en una función.

Tenga en cuenta que el artículo dice "Supongamos por un momento feliz que podríamos reescribir Swing para aprovechar al máximo la sintaxis de Scala", es decir, el artículo no pretende mostrar el código real que funciona.

Sin embargo, Scala tiene su propio paquete oscilante (scala.swing) que contiene clases que son más "scalaish" de usar que sus equivalentes java.

+0

Ah, esa cita del artículo es de hecho pertinente. Tenía la sensación de que hacer una pregunta en público iba a exponer algunas fallas básicas de comprensión de lectura por mi parte ... Aún así, su respuesta es informativa. Gracias. – PeterT

Cuestiones relacionadas