Estoy pensando en el siguiente ejemplo para ilustrar por qué la contravarianza es útil.Ejemplo de contravariancia
Consideremos un marco de GUI con Widgets
, Events
y Event Listeners
.
abstract class Event;
class KeyEvent extends Event
class MouseEvent extends Event
trait EventListener[-E] { def listen(e:E) }
Deje Widgets
definen los métodos siguientes:
def addKeyEventListener(listener:EventListener[KeyEvent])
def addMouseEventListener(listener:EventListener[MouseEvent])
Estos métodos sólo aceptan los detectores de eventos "específicas", lo cual está bien. Sin embargo, me gustaría definir también oyentes de "fregadero de cocina" que escuchen todos los eventos y pasen a dichos oyentes a los métodos de "agregar oyente" más arriba.
Por ejemplo, me gustaría definir LogEventListener
a registrar todos los eventos entrantes
class LogEventListener extends EventListener[Event] {
def listen(e:Event) { log(event) }
}
Desde el rasgo EventListener
es contravariant en Event
podemos pasar LogEventListener
a todos esos métodos "añadir oyente" sin perder su tipo de seguridad.
¿Tiene sentido?
+1 buena pregunta, mala tasa de aceptación. ¡triste! – Nishant