talosのプログラミング教室

Java Gold合格への道 ~defaultメソッド~

スポンサーリンク

こんにちは。たろすです。

今回はdefaultメソッドについて説明します。

defaultメソッドの使い方

defaultメソッドはインタフェースに記述します。

public interface A {
	default void methodA() {
		System.out.println("default method A");
	}
}
public class Impl implements A {
}
public class Main {
	public static void main(String[] args) {
		Impl impl = new Impl();
		impl.methodA();
	}
}

上から順に、インタフェース、実装クラス、メインクラスです。

実行すると次のような出力があります。

default method A

上記からわかるように、defaultメソッドはインタフェースにメソッドを実装することができます。

多重継承の場合は?

ここで多重継承の場合、両方のインタフェースに同じシグネチャのdefaultメソッドがある場合どうなるのか気になると思います。

例えば以下のような場合です。

public interface A {
	default void method() {
		System.out.println("default method A");
	}
}
public interface B {
	default void method() {
		System.out.println("default method B");
	}
}
public class Impl implements A, B {
}

この場合、コンパイルエラーとなり、以下のようなメッセージが出力されます。

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	パラメーター () および () を持つ重複した default メソッド method は型 B および A から継承されています

	at defaultMethod.Impl.<init>(Impl.java:3)
	at defaultMethod.Main.main(Main.java:5)


一方で以下のような場合はコンパイルエラーになりません。

public interface A {
	default void method() {
		System.out.println("default method A");
	}
}
public interface B extends A {
}
public interface C  extends A{
	default void method() {
		System.out.println("default method C");
	}
}
public class Impl implements B, C {
}

これはなぜかと言うと、インタフェースCはmethod()をオーバーライドしているからです。

下の図を見てみましょう。

f:id:talosta:20211029171103p:plain

インタフェースBのmethod()は実際にはインタフェースAに実装されたmethod()です。

一方でインタフェースCのmethod()はC自身に実装されたmethod()です。

インタフェースAよりインタフェースCのmethod()のほうがImplクラスに距離が近いのでインタフェースCのmethod()が優先されます。

おわりに

今回はdefaultメソッドについて説明しました。