1
0

More than 3 years have passed since last update.

なぜjavaでfinal class A{abstract class B{}}が許されるのか

Last updated at Posted at 2020-03-18

javaでは、抽象メソッドを持つクラスは必ず抽象クラス(かインタフェース)になると決まっている。
しかし抽象内部クラスを持つクラスは、別に具体的クラスでも構わないのである

例えば次のようなコードは実行可能である。

java
final class A
{
    static abstract class B{String str="hoge";}
}

public class Main
{
    public static void main(String...args)
    {
        System.out.println(new A_B().str);
      //System.out.println(new A.B(){}.str); (匿名クラス)でも別に良い
    }
} 

class A_B extends A.B{}

もし具体クラスが抽象内部クラスを持てなかったら

一見矛盾する仮定ではありますが、「マクロ(全体)に多様性を認めたくないが、ミクロ(細部)に多様性を認めたい」という場合を考えます。

このような仮定は統計力学など、ミクロとマクロの関連を考えるとき役立ちます。

例えばAir(空気)クラスとMolecule(分子)クラスを作ったとします。

分子が集まって空気を作りますので、Air has a Molecule[] といえるでしょう。

分子には水素分子、水分子、二酸化炭素分子等いろいろ考えられます。
したがって、
H2 extends Molecule, H2O extends Molecule, CO2 extends Molecule
のように継承して使う一方、「単なる分子」という分子は存在しないので、継承せずに使うことはないと思います。
そこでMoleculeは抽象クラスとなりそうです。

一方、Airには下位概念が考えにくいので、抽象クラスにしたくはありません。

ここでもし、MoleculeAirからしか呼ばれたくないメソッドを定義したくなったらどうしましょう。

いつもならMoleculeAirのインナークラスにすることで解決できます。
もし具体クラスAirが、抽象クラスMoleculeを内部に持てなかったら、多分次のような面倒くさいことをしなくちゃいけない。

  1. final public static class ${private $(){}}Airに持たせる
  2. SomethingのメソッドにAir.$型引数を持たせる

で実現する。

Air.$型はpublic staticAir以外からも見えるため、Air以外のクラスのメソッドの仮引数型として利用できる。
しかしそのコンストラクタはprivateなので、インスタンス生成はAirからしか行えない。Air以外はすなわちAir.$型実引数を渡せない。

そのおかげで、「仮引数にAir.$型を持つメソッドならば、そのメソッドはAirクラスからしか呼べない」が成立する。

実例を以下に示す。

public class Test2 {

    public static void main(String[] args) 
    {

        //new H2O.only_for_air(new Air.$()); はアクセス権限のエラー。つまりAir以外からonly_for_airを呼べない
        new Air().molecule_caller(new H2O());//Airからは呼べる

    }

}



class Air
{
    final public static class ${private $(){}}//Airの子クラスで書き換えされても困るのでfinalizeした

    void molecule_caller(Molecule m)
    {
        new H2O().only_for_air(new Air.$());
    }


}

abstract class Molecule
{
    void only_for_air(Air.$ $)
    {
        System.out.println("succeeded");
    }
}


class H2O extends Molecule{}

とまあ、こんな面倒なことをしなくちゃいけなくなる。

だから「抽象内部クラスを持つ具体的クラス」がjavaでは可能なんだろうなと思った次第。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0