Posted at

Kotlinの内部クラスを理解する


はじめに

Kotlin in Actionを読み進めているとき内部クラスが全く理解できませんでした

なので今回は内部クラスについて調べたこと実践したことをまとめてみたいと思います。

※本記事は私のはてなブログから転載したものです。


調べる

クラス内に宣言されたクラスを内部クラスと呼ぶらしいです。

これだけ説明されると普段やるクラス内にクラスを定義するのと何が違うのかという疑問が出ると思います。

以下のコードと何が違うんだろうかと、筆者がクラス内に宣言されたクラスと説明されたとき思いました。


クラスの中にクラスを定義

class ClassA {

class ClassB() {
...
}
}

疑問を解決するために調べてみたところ、

内部クラスを使うと内部クラスにとっての外部クラスのインスタンス(エンクロージングインスタンス)にアクセスできるらしいです。

以下のコードはあくまでもイメージですが、ClassBからClassAにアクセスような感じでしょうか?

class ClassA {

val id = "ClassAですよ"
class ClassB() {
fun getOuterId() : String = ClassA.id
}
}

はっきり言って説明されてもよくわからないので実際にコードを書いて確認してみます。


実践する

Kotlinではクラス定義にInner識別子をつけることで内部クラスを定義できます。

なので外部クラスとしてOuterクラス、内部クラスとしてInnerクラスを定義しました。

class Outer {

inner class Inner {

}
}

次に内部クラスの特徴であるエンクロージングインスタンスへアクセスするための仕組みを実装します。

内部クラスからエンクロージングインスタンスへはthis@クラス名.プロパティ名でアクセスできるようです。

なのでOuterクラスにIDプロパティ、InnerクラスにGetOuterIdにてthis@Outer.idでアクセスします。

class Outer {

val id = "アウターですよ"
inner class Inner {
fun getOuterId() : String = this@Outer.id
}
}

後はInnerクラスのインスタンスを生成してエンクロージングインスタンスへアクセスするのみです。

Innerクラスを生成するにはエンクロージングインスタンスが必要になるので

エンクロージングエンスタンスを生成したあとにInnerインスタンスを生成してIDプロパティを出力します。

fun main(args: Array<String>) {

val enclosing_instance = Outer()
val inner = enclosing_instance.Inner()
println(inner.getOuterId())
}

Output
------------------------------------------
アウタですよ
Process finished with exit code 0
------------------------------------------

無事、エンクロージングインスタンスにアクセスすることができました。


おわりに

調べたこと実践したことをまとめます。


  • 内部クラスを作るときはClassにinner識別子をつける。

  • 内部クラスを定義すると内部クラスのインスタンスからエンクロージングインスタンスにアクセスすることができる。

  • 内部クラスのインスタンスからthis@クラス名.プロパティ名でエンクロージングクラスにアクセスできる。

  • 内部クラスを生成するときにはエンクロージングクラスが必要になる


参考

以下の書籍・記事を参考にしながら本記事を作成しました。

* Kotlin in Action

* インナークラスとは

* エンクロージングインスタンスとは