【Java】インタフェースについて

## インタフェースとは
公開すべき必要な操作をまとめたクラスの仕様のこと。以下にインタフェースの特長をまとめる。

## インスタンス化できない
```ruby:Java(Main.java)
public class Main implements Foo {
	public static void main(String[] args) {
		Foo foo = new Foo();
	}
}

interface Foo{
	int num1 = 10;
	final int num2 = 20;
}
```

結果
```
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	型 Foo のインスタンスを生成できません

	at Main.main(Main.java:3)
```

## インタフェースの多重実現が可能
```ruby:Java(Main.java)
public class Main implements Foo,Foo2 {
	public static void main(String[] args) {
		System.out.println(Foo.num1);
		System.out.println(Foo2.num1);
	}
}

interface Foo{
	int num1 = 10;
	final int num2 = 20;
}

interface Foo2{
	int num1 = 20;
	final int num2 = 30;
}
```

結果
```
10
20
```

## インタフェースの多重継承も可能
```ruby:Java(Main.java)
public class Main implements Foo,Foo2 {
	public static void main(String[] args) {
		System.out.println(Foo.num1);
		System.out.println(Foo2.num1);
		System.out.println(Foo3.num3);
	}
}

interface Foo{
	int num1 = 10;
	final int num2 = 20;
}

interface Foo2{
	int num1 = 20;
	final int num2 = 30;
}

interface Foo3 extends Foo,Foo2{
	int num3 = 50;
}
```

結果
```
10
20
50
```

ただし以下の呼び方をするとエラーになる。

```ruby:Java(Main.java)
public class Main implements Foo,Foo2 {
	public static void main(String[] args) {
		System.out.println(Foo.num1);
		System.out.println(Foo2.num1);
		System.out.println(Foo3.num1);//エラー
	}
}

interface Foo{
	int num1 = 10;
	final int num2 = 20;
}

interface Foo2{
	int num1 = 20;
	final int num2 = 30;
}

interface Foo3 extends Foo,Foo2{
	int num3 = 50;
}
```

結果
```
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	フィールド Foo3.num1 はあいまいです

	at Main.main(Main.java:5)
```

## インタフェースで定義した変数は自動的にpublic static finalになる

```ruby:Java(Main.java)
public class Main implements Foo{
	public static void main(String[] args) {
		Foo.num1 = 20;
	}
}

interface Foo{
	int num1 = 10;
	final int num2 = 20;
}
```
結果
```
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	final フィールド Foo.num1 には代入できません

	at Main.main(Main.java:3)
```

## インタフェースで定義する変数(インスタンス変数・static変数)のアクセス修飾子はpublicのみ
デフォルトの場合は自動的にpublicに読み替えられる。protectedとprivateはエラー。

```ruby:Java(Main.java)
interface Foo{
	public int num1 = 10;
	protected int num2 = 20;//エラー
	int num3 = 30;
	private num4 = 40;//エラー
}
```
## インタフェースで定義するデフォルトメソッドのアクセス修飾子はpublicのみ
デフォルトの場合は自動的にpublicに読み替えられる。protectedとprivateはエラー。
```ruby:Java(Main.java)
	default public int number1(){
		return 10;
	}
	default protected int number2(){//エラー
		return 20;
	}
	default int number3(){
		return 40;
	}
	default private int number4(){//エラー
		return 40;
	}
```

## インタフェースで定義するstaticメソッドのアクセス修飾子はpublicとprivateのみ
デフォルトの場合は自動的にpublicに読み替えられる。protectedはエラー。
```ruby:Java(Main.java)
	public static int number1() {
		return 10;
	}
	protected static int number2() {//エラー
		return 20;
	}
	static int number3() {
		return 30;
	}
	private static int number4() {
		return 40;
	}
 ```

 ## インタフェースに定めたメソッドは実現しないといけない
```ruby:Java(Main.java)
 public class Main {
	public static void main(String[] args) {
		Add add = new Add();
		System.out.println(add.calc(2,7));
	}
}

interface Foo{
	public int calc(int a,int b);
}

//Fooの継承
//Calcメソッド実装
class Add implements Foo{
	public int calc(int a,int b) {
		return a + b;
	}
}
```

結果
```
9
```

## デフォルトメソッドでjava.lang.Objectのメソッドをオーバーライドできない
```ruby:Java(Main.java)
interface Foo{
	default String toString() { //エラー
		return "aaa";
	}
}
```

## 元のデフォルトメソッドを呼び出す場合、インタフェース名.super.メソッド名で呼び出す
```ruby:Java(Main.java)
public class Main {
	public static void main(String[] args) {
		Add add = new Add();
		System.out.println(add.calc(2,7));
		System.out.println(add.callSuperNum(2,7));
	}
}

interface Foo{
	default int num(int a,int b) { 
		return a * b;
	}
}

//Fooの継承
//Calcメソッド実装
class Add implements Foo{
	public int calc(int a,int b) {
		return a + b;
	}
	public int callSuperNum(int a,int b) {
		return Foo.super.num(a, b);
	}
}

```
結果
```
9
14
```

## 共変戻り値について
これはインタフェースを実装したメソッド、またはサブクラスでオーバーライドするメソッドの戻り値が、その戻り値のサブクラスでも良いという仕様。

```ruby:Java(A.java)
public interface A{
	public Iterable a();
}
```
```ruby:Java(B.java)
import java.util.Collection;

public interface B extends A{
	public Collection a();
}
```
```ruby:Java(C.java)
import java.nio.file.Path;

public interface C extends A{
	public Path a();
}
```

BインタフェースとCインタフェースでaメソッドを実装しているが、ＡインタフェースのIterable型で戻していない。IterableインタフェースはCollectionやPathのスーパーインタフェースなので、問題無く動く。

## まとめ
* インスタンス化できない
* インタフェースの多重実現が可能
* インタフェースの多重継承も可能
* インタフェースで定義した変数は自動的にpublic static finalになる
* インタフェースで定義する変数(インスタンス変数・static変数)のアクセス修飾子はpublicのみ
* インタフェースで定義するデフォルトメソッドのアクセス修飾子はpublicのみ
* インタフェースで定義するstaticメソッドのアクセス修飾子はpublicとprivateのみ
* インタフェースに定めたメソッドは実現しないといけない
* デフォルトメソッドでjava.lang.Objectのメソッドをオーバーライドできない
* 元のデフォルトメソッドを呼び出す場合、インタフェース名.super.メソッド名で呼び出す
* 共変戻り値とはインタフェースを実装したメソッド、またはサブクラスでオーバーライドするメソッドの戻り値が、その戻り値のサブクラスでも良いという仕様