インターフェース(Java)

## インターフェースとは
プログラムを作成するときに、決められた操作を行うためのメソッドがまとめて定義されているクラスのようなもの。そのクラスで使うメソッドをインターフェースで定義しておく。インターフェースではメソッドの中身は空にしておいて、インターフェースを使うクラス内で中身を実装することが多い。
```java
//インターフェース
interface インターフェース名{
    //メソッド定義
    void method A(){}
    void method B(){}
}

//インターフェースをクラスに実装
class A implements インターフェース名 {
    public void methodA {
        //実装する
    }
}
```

## 使用場面
<font color="DarkOrange">**クラス間の関係性を定義する場合:**</font> インタフェースは、複数のクラスが共通のメソッドや振る舞いを持つ場合に使用される。例えば、異なるクラスが同じインタフェースを実装することで、それらのクラスが共通の操作を提供することができる。これにより、クラス間の関係性を明確に定義し、柔軟性と拡張性を向上させることができる。

<font color="DarkOrange">**多態性を実現する場合:**</font> インタフェースはポリモーフィズムを実現するために使用される。異なるクラスが同じインタフェースを実装することで、それらのクラスのインスタンスを統一的に扱うことができる。プログラム内でインタフェース型を使用することで、実行時に適切なクラスのメソッドが呼び出されるため、柔軟なオブジェクトの操作が可能となりる。

<font color="DarkOrange">**コードの再利用性を高める場合:**</font> インタフェースは、複数のクラスで共通のメソッドを定義することにより、コードの再利用性を高める。インタフェースを実装することで、複数のクラスで同じインタフェースメソッドを再利用することができる。また、新しいクラスを追加する際に、既存のインタフェースを実装するだけで、既存のコードとの互換性を保つことができる。

## インターフェースの役割
#### 1. ポリモーフィズムを実現する
オブジェクト指向におけるポリモーフィズム(多様性)を実現する。
ポリモーフィズムとは、複数のオブジェクトが同じ命令に対して違う挙動を可能にすること。
例えば猫、犬、鳥のオブジェクトがあった時、どれも鳴くという共通の命令はあるが、それぞれ「にゃー」「わん」「ピヨ」と挙動は違う。
この鳴くという共通の動作の入り口を定義することがインターフェースの役割。
```.java
interface Animal {
    void cry();
}

//同じcryメソッドを使用しているが、出力される結果はそれぞれ違う
class Cat implements Animal {
    public void cry() {
        System.out.println("にゃー");
    }
}

class Dog implements Animal {
    public void cry() {
        System.out.println("わん");
    }
}

class Bird implements Animal {
    public void cry() {
        System.out.println("ピヨ");
    }
}
```

#### 2.実装漏れを防ぐ
インターフェースで定義したメソッドは必ず、実装クラスでオーバーライドしなければならない。
オーバーライドしなかった場合はコンパイルエラーが出るので実装漏れを防ぐことができる。

#### 3.柔軟性と拡張性をあげる

```.java
public interface Calculation  {
    int sum(int num);
}
```
```.java
public class A implements Calculation {
    @Override
    public int sum(int num) {
        int price = num + 100;
        return price;
    }
}

public class B implements Calculation {
    @Override
    public int sum(int num) {
        int price = num + 200;
        return price;
    }
}
```
Calculationインタフェースをパラメータとして受け取っている。このように、メソッドの引数や戻り値としてインタフェースを使用すると、Calculationインタフェースを実装したクラスなら全て受け取れる柔軟性が生まれる。
```.java
public class Main {
 
    public static void main(String[] args) {
 
        A a = new A();
        B b = new B();
        //同じ記述で呼び出せる
        settlement(a);
        settlement(b);
    }
 
    public static void settlement(Calculation calculation) {
        int num = calculation.sum(100);
        System.out.println("計算結果：" + num);
    }
}
```

## defaultメソッド
予め中身の処理が書かれているメソッドをインターフェースで実装することができるメソッド。
メソッドの型の宣言の前にdefault句を記述する。
```.java
interface Animal {
    default void sleep() {
        Sysyem.out.println("寝てます");
    }
}

class Cat implements Animal {
    @Ovierride
    public void sleep() {
        Animal.super.sleep(); //継承元のデフォルトメソッドの呼び出し
    }
}
```


## ネストしたインターフェース
インターフェースの中にクラスを宣言することも可能。
インターフェース内のクラスは常にpublicかstatic。慣習的にpublicとstaticは省略する。
```java
interface Animal {
    class Cat {
        private String name;
        public Cat(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
    }
    Cat getCat();
}

class MyImpl implements Animal {
    @Ovierride
    public Cat getCat() {
        return new Animal.Cat("猫");
    }
}

Animal animal = new animal();
Animal.Cat cat = animal.getCat();
System.out.println(cat.getCat());
```

## 多重継承
同じシグネチャのメソッドを持つ2つのインターフェースを多重継承したクラスは、そのメソッドの実装を１つ持てば良い。
```.java
interface A {
    void method();
}

interface B {
    void method();
}

class C implements A,B {
    //methodメソッドは1つで良い
    @Ovierride
    public void method() {
        System.out.println("メソッド");
    }
}
```

異なるシグネチャのメソッドを持つ２つのインターフェースを多重継承した場合は、それぞれのメソッドを実装する。
```.java
interface A {
    void methodA();
}

interface B {
    void methodB();
}

class C implements A,B {
    @Ovierride
    public void methodA() {
        System.out.println("メソッドA");
    }

    @Ovierride
    public void methodB() {
        System.out.println("メソッドB");
    }
}
```

多重継承した２つのインターフェースが継承関係のある型の返り値を持つ同名のメソッドを持っていた場合は、継承関係で下の方に位置する型のメソッドを実装すれば良い

```.java
interface A {
    Object methodA();
}

interface B {
    String methodA();
}

class C implements A,B {
    //Object→StringなのでStringの方を実装する
    @Ovierride
    public String methodA() {
        System.out.println("メソッドA");
    }
}
```