こんにちは!ぱかぱかです!
今日は仕事納めということで1年の振り返りでも書きたいところだったのですが、業務でインナークラスの話になり、いまいちよくわかっていないなと思ったのでまとめておくことにしました。
(振り返りは年末ギリギリまで取っておくことにします笑)
なんか今までの記事の流れを見るとだいぶ唐突なのですが、鉄は熱いうちに打っておきましょう。
Java Goldでも黒本の第1章とか最初の方で出てくるような内容なので知ってはいるけど、いまいち使い所がよくわかっていないという…
SwiftやKotlinなど他の言語でも同じような概念が存在するようですが、今回はJavaベースでまとめておきます。
ネストクラス
ネストクラスとはずばり、クラスの中に定義されたクラスのことです。
外側のクラスのメンバとして、内側のクラスがいる状態になります。
ちなみに外側のクラスのことをエンクロージングクラスとも言います。
class Outer { class A {} // 非staticクラス → インナークラス static class B {} // staticクラス }
ネストクラスにはstaticクラスおよび非staticクラスが定義できますが、特に非staticクラスのことをインナークラスと呼びます。
インナークラスにはさらにローカルクラスと匿名クラスが存在しますが、そちらは後の方にまとめたいと思います。
ネストクラスへのアクセス
ネストクラス内で定義したメンバはネストクラスをインスタンス化することで利用できます。
上のコード例でクラスをインスタンス化する場合は以下のような書き方になります。
非staticクラス(インナークラス)
外側クラス名.非staticクラス名 変数名 = new 外側クラス名().new 非staticクラス名();
Outer.A a = new Outer().new A();
staticクラス
外側クラス名.staticクラス名 変数名 = new 外側クラス名().staticクラス名();
Outer.B b = new Outer().B();
staticメンバなのでnewしなくても呼び出せるというお話で、書き方が違うだけですかね。
インナークラスの種類
非staticクラス(インナークラス)の種類にもまとめておきます。
ローカルクラス
ローカルクラスはあるクラスのメソッド内に定義したクラスのことです。
スコープはメソッド内で制限され、定義されているメソッド内でのみインスタンス化できます。
class Outer { void method() { class A {} // ローカルクラス } }
匿名クラス
匿名クラスはクラス名を指定せずにクラス定義とインスタンス化を1つの式として記述したクラスのことです。
再利用されることがなく特定の場所のみで実装したい場合に使用します。
class Outer { void method() { new スーパークラス名またはインターフェース名() {} // 匿名クラス }; }
あまり意識していませんでしたが、SAM変換していないAndroidのsetOnClickListenerとかで匿名クラスが出てきてますかね。
(ネストクラスとは関係ないかもですが…)
View.onClickListenerインターフェイスを継承した匿名クラスを第1引数に取っていて、インターフェースのonClickメソッドをoverrideしています。
view.setOnClickListener(object: View.OnClickListener { override fun onClick(view: View?): Unit { } })
ネストクラスのメリット
色々細かいルールは他にもあるのですがそこら辺は端折ってます。
今回知っておきたかったネストクラスのメリットとしては以下のようなところになります。
メリット
・使用場所が限定されその存在を外部から隠すことができる。
・ソース上で依存関係を表せる。
・外側のインスタンス化を強制できる。
使われる場所が限定されるようなクラスは内部クラスで持っておくというのも1つの手かもしれないですね。
ただあまり実装では使われているところを見かけません…
クラスを普通に分けておくのでもいいような気もしますが、依存関係を意識することを強制できるのがいいのかな…
結局使い方は復習できたけど、ここぞという使い所は掴めず…
何かいい例があったら教えていただきたいです。
短いですが今回はこれくらいにします。
ではまた!