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) }
}

トレイトEventListener反変であるため、型の安全性を失うことなく、これらすべての「リスナーの追加」メソッドにEvent渡すことができます。LogEventListener

それは理にかなっていますか?

4

2 に答える 2

7

とにかく、それは私には理にかなっています。また、これは私が見た中で最も直感的な例の 1 つでもあります。すべてのイベントを自然にリッスンするものは、キー イベントまたはマウス イベントをリッスンします。

于 2011-03-18T13:43:49.190 に答える
7

私にとっても理にかなっています。経験則として、パラメーター化された型は、パラメーターとして受け入れることによってそれらで何かを行うために のインスタンスを受け入れることを意味するたびType[A]に、その型パラメーターに関して反変でなければなりません。A A

たとえば、Java の typeComparator[T]は、Scala で定義されていた場合、反変になります。aは、a が比較できるすべてのオブジェクトを比較できるため、Comparator[Any]a のサブタイプである必要があります。最も一般的な例は、すべて反変であるクラスの引数の型です。Comparator[String]Comparator[String]FunctionX

于 2011-04-17T20:27:33.483 に答える