365連休

にわかのandroidとかの開発メモ。

【Javaジェネリクス】自身(継承クラス)を返す抽象メソッド、擬似自己型(自己参照型ジェネリクス)

抽象クラスで「継承したサブクラスのインスタンスを返す抽象メソッド」を定義したくて調べていたら、素晴らしい記事を発見ました。

日本語サイトでは唯一?の秀逸な技術情報だったので、拡散しなければもったいないと思いリツイート的に記事にします。

 

relearn-java.com

 

    abstract class AbsData {
        abstract AbsData self();
    }
    class ExData extends AbsData{
        @Override
        AbsData self() { //    ExData self(); 実はこう書いても怒られない
            return this;
        }
    }

 

 でも、できたらExDataを返すよう強制したいよね。

と思ったら ↓ こうできる。

 

    abstract class AbsData<T extends AbsData<T>> { //擬似自己型 T
        abstract T self();
    }
    class ExData extends AbsData<ExData>{ //ジェネリクスを指定すると
        @Override
        //AbsData self() { //ジェネリクスに従った戻り値じゃないとコンパイルエラー
        ExData self() {
            return this;
        }
    }

 

 

Android Studio 3.4 で[コード]-[メソッドのオーバーライド]を行うと一気にコード補完されて便利ですが、この時、上記の擬似自己型テクニックを用いると期待したコードが生成されます。

 

 

2021/2/15追記

final宣言された継承クラス(子)について有効だと思います。

例:Enum<E extends Enum<E>> ※enumの実態はEnumクラスを継承しfinal。

 

publicな子クラスとさらに継承した孫クラスがあるとき、継承しにくかったり継承メソッドを使いづらかったり副作用があると感じました。