Mic*_*ael 29 scala contravariance
我正在考虑以下示例来说明为什么逆变是有用的.
让我们考虑一个GUI框架Widgets
,Events
和Event Listeners
.
abstract class Event;
class KeyEvent extends Event
class MouseEvent extends Event
trait EventListener[-E] { def listen(e:E) }
Run Code Online (Sandbox Code Playgroud)
我们Widgets
定义以下方法:
def addKeyEventListener(listener:EventListener[KeyEvent])
def addMouseEventListener(listener:EventListener[MouseEvent])
Run Code Online (Sandbox Code Playgroud)
这些方法只接受"特定"事件监听器,这很好.但是我想定义"kitchen-sink"监听器,它们监听所有事件,并将这些监听器传递给上面的"添加监听器"方法.
例如,我想定义LogEventListener
记录所有传入的事件
class LogEventListener extends EventListener[Event] {
def listen(e:Event) { log(event) }
}
Run Code Online (Sandbox Code Playgroud)
由于特征EventListener
是逆变的,Event
我们可以传递LogEventListener
给所有那些"添加监听器"方法而不会失去其类型安全性.
是否有意义 ?
对我也有意义.根据经验,参数化类型Type[A]
在A
每次A
通过接受它们作为参数来接受与它们做某事的实例时,应该相对于它的类型参数是逆变的.
例如,Java类型Comparator[T]
(如果已在Scala中定义)将具有逆变性:a Comparator[Any]
应该是子类型Comparator[String]
,因为它可以比较可以比较的所有对象Comparator[String]
,等等.最一般的例子是类的参数类型FunctionX
,它们都是逆变的.
归档时间: |
|
查看次数: |
2028 次 |
最近记录: |