interfaceにdefaultメソッドを追加すると設計がどう変わるか?
interfaceにdefaultメソッドを追加すると設計がどう変わるか?
Java 8で導入されたdefault
メソッドは、interfaceに実装を直接持たせる機能です。
もともとJavaのinterfaceは純粋に“契約のみを定義する”ものでしたが、defaultメソッドの登場によって、インターフェースでありながら実装を含めるという設計が可能になりました。
これは柔軟性をもたらす一方で、責務の分離や構造の明示性を損なうことにもつながります。
この記事では、defaultメソッドを設計に取り入れる際のメリット・落とし穴・レビュー観点を整理します。
defaultメソッドとは何か?
public interface Printer {
void print(String content);
default void printWithHeader(String content) {
System.out.println("=== HEADER ===");
print(content);
}
}
構文の背景
元々はJava 8のStream
APIのように、既存interfaceに後方互換性を保ったまま新機能を追加するために導入された。
技術的メリット──なぜ導入されたのか?
- 既存のinterface利用者に影響を与えず、新たな振る舞いを追加できる
- Utility的な振る舞いをinterface側にまとめられる
- クラス階層の肥大化を防げる(必要な分だけ追加)
OKな使い方例:完全にユーティリティである場合
public interface Timer {
void start();
default void logStart() {
System.out.println("Start at: " + System.currentTimeMillis());
}
}
logStart()
は状態に依存しない- 他の実装に影響を与えない
- 利用側がoverrideする必然性も低い
問題の所在──責務がインターフェースに混ざる
1. インターフェースの契約が“行動仕様”を持ち始める
public interface UserRepository {
User find(String id);
default User findOrThrow(String id) {
User user = find(id);
if (user == null) throw new NotFoundException();
return user;
}
}
→ 「nullを許容するのか?」という仕様差異が実装レベルに入り込み、interfaceに残ってしまう
2. 実装クラス側の責務が不明瞭になる
public class CachedRepository implements UserRepository {
@Override
public User find(String id) {
// キャッシュロジック
}
// findOrThrowはdefaultのまま
}
→ findOrThrow
の仕様にキャッシュは絡んでいない
→ 実装責務の一貫性が保てない
3. テスト対象が複雑になる
- default実装がどこに属しているか分かりにくい
- モック時にdefaultメソッドを差し替えられない
- interfaceの責務が大きくなりすぎる
結局、defaultメソッドはどういうときに“アリ”か?
判断軸 | OKなケース | NGなケース |
---|---|---|
後方互換性維持 | 既存APIへの追加 | 新規設計にdefault前提で導入 |
実装不要なユーティリティ | printlnなどの補助関数 | データベースアクセスなどの処理 |
状態や副作用を持たないか | 引数のみで完結する処理 | 状態保存やDB操作を含む処理 |
責務が明確に分離されているか | ログ・変換・検査など | ビジネスロジックを含む処理 |
defaultメソッドの曖昧性
レビュー観点:defaultメソッドの責務混在に注意
レビュー観点
defaultメソッドをinterfaceに追加している設計を見たら、次の観点を確認してください。
defaultメソッドは“便利な妥協”ですが、設計構造を壊すほどに頼るものではありません。
結論:defaultメソッドは「互換性の例外措置」であって、「拡張の手段」ではない
Javaのinterfaceにおけるdefaultメソッドは、既存構造の壊さないための折衷策であり、
それを前提にした設計構造を取るべきではありません。
- 状態や副作用を含む処理はクラスに明示すべき
- 振る舞いの拡張は抽象化によって行うべき
- interfaceはあくまで契約の定義に留める