Java 8 からはインターフェースにデフォルトの実装を持てるようになった。Java でデフォルトの実装を持たせる場合、Java 7 までは必ず抽象クラスを経由する必要があったが、Java 8 からは 本機能を利用することで実現が可能になった。
簡単な default 実装の利用方法
default というキーワードを利用して、以下のようにインターフェースに対して標準の実装を持たせることができる。
public interface HelloService{ defualt String sayHello(String name){ return name + "さん、こんにちは"; } }
もちろんインターフェースは直接インスタンス化できないが、標準的な処理をあらかじめインターフェースに定義することができるため「これだけはこういう実装をして欲しい」という部分をインターフェースに定義可能になったと言える(標準化というものに携わる人にはちょっとうれしい機能な気がする)。
もうちょっと突っ込んでみる
以下のサンプルを実行してみた。
- HelloService.java
package org.mydomain.defaultinterface; // インターフェースには暗黙的に final, public, static が付与されるが、 // 今回は明示的に上記の予約語を付与 public interface HelloService { // 普通はこんな定義はしないで、あくまで実験用としていただけると public static final MyDto dto = new MyDto(); public String sayGoodBye(String name); default public String sayHello(String name) { dto.setName(name); System.out.println("ここは侵されていないデフォルトメソッド(*´Д`)ハァハァ"); return name + "さん、卑猥ですね!"; } } class MyDto { String name; public MyDto() { name = "何とも卑猥"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
- Main.java
package org.mydomain.defaultinterface; public class Main { public static void main(String[] args) { HelloService service = new HelloService() { @Override public String sayGoodBye(String name) { System.out.println("実装してみた系"); return name + "さん、さようなら(/ω\)イヤン"; } }; System.out.println("名前 = " + HelloService.dto.getName()); System.out.println(service.sayHello("卑猥")); System.out.println(service.sayGoodBye("淫猥")); System.out.println("名前 = " + HelloService.dto.getName()); System.out.println(); // もちろんメソッドの上書きも可能 HelloService service2 = new HelloService() { @Override public String sayHello(String name) { return "もう何もない"; } @Override public String sayGoodBye(String name) { return null; } }; System.out.println(service2.sayHello("aaa")); } }
- 実行結果
名前 = 何とも卑猥 ここは侵されていないデフォルトメソッド(*´Д`)ハァハァ 卑猥さん、卑猥ですね! 実装してみた系 淫猥さん、さようなら(/ω\)イヤン 名前 = 卑猥 もう何もない
ご覧のとおり、デフォルト実装を定義した場合でも実装クラスにおける処理の上書きは可能であり、インターフェースで状態は持てないことがわかる(final static public なインスタンスは状態が持てるが、これは Java 7 以前からと同様)。
じゃあインターフェースと抽象クラスの区別は?
インターフェースと抽象クラスとの区分けが気になるところだが、以下の言質をいただいておる。
Java 8 から abstract と interface の区別があいまいになってきた気がするな
@normalian もともとインターフェイスってダイアモンド継承問題の解決策だから、フィールドさえ持ってなければなんでも。
2014-01-01 14:21:52 via web to @normalian
@normalian その多重継承とか状態持てるかどうかの可否が、ダイアモンド継承問題の解決策。なので実はデフォルト実装持てるかどうかとかはたいした問題じゃなくて、別にぶれてないと思うよ。
2014-01-01 14:35:12 via web to @normalian