29

我正在考虑以下示例来说明为什么逆变是有用的。

让我们考虑一个带有WidgetsEvents和的 GUI 框架Event Listeners

abstract class Event;
class KeyEvent extends Event
class MouseEvent extends Event

trait EventListener[-E] { def listen(e:E) }

让我们Widgets定义以下方法:

def addKeyEventListener(listener:EventListener[KeyEvent])
def addMouseEventListener(listener:EventListener[MouseEvent])

这些方法只接受“特定”事件侦听器,这很好。但是,我还想定义“厨房水槽”侦听器,它侦听所有事件,并将此类侦听器传递给上面的“添加侦听器”方法。

例如,我想定义LogEventListener记录所有传入事件

class LogEventListener extends EventListener[Event] {
   def listen(e:Event) { log(event) }
}

由于 traitEventListener逆变的,Event我们可以传递LogEventListener给所有这些“添加侦听器”方法,而不会失去它们的类型安全性。

是否有意义 ?

4

2 回答 2

7

对我来说也很有意义。根据经验,参数化类型Type[A]应该是逆变的,A 每次它意味着A通过接受它们作为参数来接受实例来对它们做某事时,它的类型参数应该是逆变的。

例如,Java 类型Comparator[T],如果它是在 Scala 中定义的,它将是逆变的:aComparator[Any]应该是 的子类型Comparator[String],因为它可以比较 a 可以比较的所有对象Comparator[String],等等。最普遍的例子是FunctionX类的参数类型,它们都是逆变的。

于 2011-04-17T20:27:33.483 回答
7

无论如何,这对我来说很有意义。这也是我见过的最直观的例子之一:监听所有事件的东西自然会监听按键事件或鼠标事件。

于 2011-03-18T13:43:49.190 回答