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
このように指定された変位と矛盾するような操作が可能なとき、コンパイラが文句を言ってくれるようになりました。
かしこい! 以上です。