反省はしても後悔はしない

Vim とか備忘録とか。それと関数型言語勉強中

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) // 共変 + 反変

結果として、上記は正常にコンパイルできます。メソッドの引数については「反変」、戻り値については「共変」が常に許されるみたいです。