拡張メソッドについて調べてみた その1
【前提条件】
【拡張しやすいとは】
今までインターフェイスにメソッドを追加した場合は
実装したすべてのクラスにメソッドを実装する必要がありました。
拡張メソッドはインターフェイスにデフォルトの実装を持たせるものです。
その名のとおり各クラスから拡張メソッドが呼び出された場合、
デフォルト実装の処理が実行されます。
拡張メソッドはオーバーライドすることができるので、
拡張メソッドの内容を変更する場合はオーバーライドします。
【ソースコード】
[インターフェイス]
では実際に拡張メソッドを定義したインターフェイスを見てみます。
public interface SampleInterface { void executeImplements(); default void executeDefault() { System.out.println("executeDefault executed!"); } }
[実装したクラス]
拡張メソッドを定義する場合はメソッドにdefaultをつけて、
通常のメソッドとして処理を記述します。
public class Sample01 implements SampleInterface{ public static void main(final String[] args) { final Sample01 sample = new Sample01(); sample.executeImplements(); sample.executeDefault(); } @Override public void executeImplements() { System.out.println("Sample1 implements excute."); } } public class Sample02 implements SampleInterface{ public static void main(final String[] args) { final Sample02 sample = new Sample02(); sample.executeImplements(); sample.executeDefault(); } @Override public void executeImplements() { System.out.println("Sample2 implements excute."); } @Override public void executeDefault() { System.out.println("Override default!"); } }
Sample01ではexecuteImplementsメソッドのみ実装しています。
Sample02ではexecuteImplementsメソッド、executeDefaultメソッドを実装しています。
[実行結果]
<<サンプル1の実行結果>> Sample1 implements excute. executeDefault executed! <<サンプル2の実行結果>> Sample2 implements excute. Override default!
実行結果を見るとサンプル1側のexecuteDefaultメソッドは
デフォルト実装が実行されていることがわかります。
サンプル2側のexecuteDefaultメソッドは
オーバーライドしたメソッドが実行されていることがわかります。
【Abstractクラス】
Abstractクラスは通常のメソッドと
各クラスが実装する必要がある抽象メソッドを持つことができるクラスです。
インターフェイスに拡張メソッドが追加されたので、
Abstractクラスとの違いがあいまいになりそうです。
拡張メソッドを使えばAbstractクラスと同様のことができますが、
以下のような違いがあるため、単純な置き換えにはなりません。
Abstractクラスを使ったTemplateMethodパターンは
拡張メソッドに置き換えることができません。
処理の流れをつかさどるメソッドもオーバーライドできるため
TemplateMethodパターンが構築できません。
最近はAOPを使うことが多いのでTemplateMethodパターンを
Abstractクラスで実現するは少ないと思いますが。
【lambda内でのデフォルトメソッド】
前回、forEachメソッドについて書きましたが、
forEachメソッドもIterableインターフェイスに追加された拡張メソッドです。
public class Sample03 { public static void main(final String[] args) { final List<String> valueList = new ArrayList<>(); valueList.add("one"); valueList.add("two"); valueList.add("three"); final Iterable<String> ite = valueList; ite.forEach(System.out::println); } }
Iterable#forEachで動作していることがわかります。