Scala の関数の変位について調べてみた
ジェネリックの変位についてはいろいろ資料とかあるんだけど、関数の変位ってどうなってるのか少し疑問だったので調べて見ました。
どういうこと?
たとえば、以下のようなイベントがあったときに
def onLoad(callback: Event => Unit) def onClick(callback: MouseEvent => Unit)
以下のように呼べるかということです。(MouseEvent は Event を継承しています)
def handler(e: Event) {
alert(e.message)
}
onLoad(handler)
onClick(handler)
onLoad に対して、Event => Unit な関数を渡すのはいいとして、MouseEvent => Unit な関数を受け取る onClick に対しても呼び出してもいいのかということですね。(これは「反変」の例)
いろいろためしてみた
共変・反変の説明は他に譲るとして、いろいろ試してみました。
class Base {} class Derived extends Base {} def hoge(func: Derived => Base) {} def dd(d: Derived): Derived = new Derived def db(d: Derived): Base = new Base def bd(b: Base): Derived = new Derived def bb(b: Base): Base = new Base hoge(db) // 完全に一致 hoge(dd) // 戻り値の型が派生型 (共変) hoge(bb) // 引数の方が基本型 (反変) hoge(bd) // 共変 + 反変
結果として、上記は正常にコンパイルできます。メソッドの引数については「反変」、戻り値については「共変」が常に許されるみたいです。