読者です 読者をやめる 読者になる 読者になる

算譜王におれはなる!!!!

偏りはあると思うけど情報技術全般についてマイペースに書くよ。

Kotlin M10リリースされた

本日Kotlinのマイルストーン10がリリースされました。

http://blog.jetbrains.com/kotlin/2014/12/m10-is-out/

いい感じですね。JS対応が面白くなってきました。今度まとめたいと思います。

今回は宣言箇所分散(declaration-site variance)まわりのコンパイラチェックが改善された点について。

M10より前の話

Kotlinはクラスの宣言箇所にて型引数の変位指定ができます。

class Container<T>(val value: T)

こんなクラスがあったとして。

val a: Container<Int> = Container(5)
val b: Container<Number> = a // Containerは不変なのでここはコンパイルエラー
val c: Container<out Number> = a // ここで共変を意味するoutを指定しているのでOK

まーこんな感じですね。Javaと同じです。Javaの場合はContainer<? extends Number>ですね。

で、このContainerですが、T型のvalueは読み取り専用です。値が変わることはありません。 なので共変として扱っても安全です。これはクラスの宣言時にわかっています。 そこで便利なのが宣言箇所分散です。 先ほどは変位指定をクラスの使用箇所で行っていましたが、これをクラスの宣言箇所で行えます。

class Container<out T>(val value: T)

これにより、次のようなコードがコンパイルを通ります。

val a: Container<Int> = Container(5)
val b: Container<Number> = a // 既にout指定されているのでOK

便利ですね。 ちなみに共変指定はout、反変指定はinです。読み取り専用のout、書き込み専用のinと覚えるといいかも。

ここで問題があります。 共変指定をしておきながら書き込みを許すように定義してもコンパイラは文句をいいません。

class Container<out T>(var value: T) // valをvarに変更

val a: Container<Int> = Container(5)
val b: Container<Number> = a // コンパイルOK
b.value = 0.5 // コンパイル & 実行OK (なぜか)

M10

このように指定された変位と矛盾するような操作が可能なとき、コンパイラが文句を言ってくれるようになりました。

f:id:ngsw_taro:20141217220717p:plain

かしこい! 以上です。