2026年2月22日日曜日

【Java進化史 第22回 後編】defaultメソッドの注意点 〜 どこまで“クラス化”したのか 〜

【Java進化史 第22回 後編】defaultメソッドの注意点 〜 どこまで“クラス化”したのか 〜

前回、インターフェースに実装を書くという事実に、 正直な違和感を覚えた。

今回は、少し冷静に整理してみる。

defaultメソッドは、 どこまで許されているのか。

■ defaultメソッドは何ができるのか

まずは単純な例から。


public interface Sample {

    int VALUE = 10; // 定数は持てる(public static final)

    int calc(int x);

    default int doubleCalc(int x) {
        return calc(x) * VALUE;
    }
}

ここで注目すべき点は2つある。

  • インターフェースは定数(public static final)しか持てない
  • defaultメソッドは他の抽象メソッドを呼び出せる

つまり、 defaultメソッドは「振る舞いの共通化」はできる。

しかし、 状態は持てない。

インスタンスフィールドは宣言できない。 コンストラクタもない。

ここは、クラスとは決定的に違う。

defaultメソッドは、 クラスの代わりではない。

あくまで、 契約の延長線上にある“補助的な実装”だ。

■ 多重継承はどうなるのか

では、インターフェースが複数あったらどうなるのか。


interface A {
    default void hello() {
        System.out.println("A");
    }
}

interface B {
    default void hello() {
        System.out.println("B");
    }
}

class C implements A, B {
}

これはコンパイルエラーになる。

どちらのhelloを使うのか、 曖昧だからだ。

Javaは、この曖昧さを許さない。

必ず、実装クラス側で明示的に解決する必要がある。


class C implements A, B {

    @Override
    public void hello() {
        A.super.hello();
    }
}

このように、 どのインターフェースの実装を使うかを 明示的に指定する。

「なんとなく動く」は許されない。

■ 原則は壊れていない

インターフェースは、今でも状態を持たない。

完全なクラスになったわけではない。

defaultメソッドは、 無制限の自由ではない。

制御された拡張である。

だからこそ、 長年守られてきた設計思想は、 完全に崩れたわけではない。

むしろ、 後方互換性を守りながら進化するための、 現実的な選択だったと言える。

違和感はある。

だが、無秩序ではない。

そこが、Javaらしさなのかもしれない。




0 件のコメント:

コメントを投稿

【Java進化史 第23回】Java8でBase64は何がどう変わったのか 〜 地味だが確かな進化 〜

【Java進化史 第23回】Java8でBase64は何がどう変わったのか 〜 地味だが確かな進化 〜 風の噂で聞いた。 Java8でBase64が正式に追加されたらしい。 「いや、前からあっただろう?」 そう思った人も多いはずだ。 確かに、Java...