第 10 章 インタフェース

インターフェース (ミックスイン) の説明は大体想像通りなのだが、クラスデリゲーションの仕組みだけなるほどと思った:

class GreeterWithRecording(private val greeter: Greeter) : Greeter by greeter {
    private val _targets: MutableSet<String> = mutableSetOf()
    val targets: Set<String>
        get() = _targets
    override fun sayHello(target: String) {
        _targets += target
        greeter.sayHello(target)
    }
}

上記のような例が紹介されていた。by greeter の部分がオーバライドしていないメンバは greeter に依存するという意味らしい。うまい説明ができないので詳しくは本誌参照のこと。

第 11 章 ジェネリクス

最初の理解としては大体 Java と同様なのだが、以下の記述は書きにくいのではないかと思った:

class Baz<T> where T : Hoge, T : Fuga  // T は Hoge と Fuga インターフェースを実装している

直感的には class Baz<T : Hoge, Fuga> なのだが。

Java も Kotlin もジェネリクスの実装は不変だが Kotlin のジェネリクスは共変や反変にすることもできる。 例えば A<T> のところを A<out T> (共変) や A<in T> (反変) などと記述する。

例えば Array<String>Array<CharSequence> ではない (StringCharSequence のサブタイプ) が Array<out CharSequence> だと Array<String> が含まれるし Array<in String> だと Array<CharSequence> も含まれるということ。

最後に具象型というトピックがあった。Kotlin のジェネリクスは Java と同様に実行時に型情報が消去される (Java では常に型パラメータは Object となる) が、そうではなく型情報を保持した状態で期待する動作を実現する方法があるらしい。

inline fun <reified T> Any.instanceOf(): Boolean = this is T

このような関数が紹介されており reified というキーワードが付いている。 普通の Java だと T は常に Object となるので is キーワードによる型チェックは失敗しそうに見えるが、これなら成功するらしい。

第 12 章 Null 安全

ここに書いてある内容は Swift などと同様なので新たに知ったような事は少ない。 普通こういった機構はオプショナルというが Kotlin では Nullable というようだ。

第 13 章 その他の話題

モダンな言語には大抵付いている演算子オーバーロードの話題から始まっていた。 Kotlin では operator fun ... で書くと演算子オーバーロードとなる。 あまり乱用すると訳が分からなくなるので、明らかに分かりやすくなるケースのみに使用していくのが良いかと思う。

その次は等価性の話題となっていた。 Kotlin では Java のように参照の一致を検査したい場合 === 演算子を使用する。 Kotlin では == 演算子は equals() と同等の意味となっている。 Java だと == が参照の一致の検査になっているせいで文字列の一致の比較など "str".equals(b) などといちいち書かなければならないので不便だった。

次が中置呼び出しに関する話題だった。 infix キーワードで定義するもので、例えば MyInt(1) plus MyInt(2) などという中置記法が可能となる。 ビルトインのものだと 1..10 step 3step が中置呼び出しとなっている。