おいでよ Interfaceの森

僕が勉強し始めたときに勝手に定義した<b>3大なんであるのこの構文</b>のひとつ、<b>Interface</b>さん。

この人が<b>どういうときに使われるの？</b>
<b>果たして本当に必要な構文なの？</b>

というところを紐解いて行こうと思います。

<font color="E0E0E0">ちなみに、どうてもいいですが残りの3大なんであるのこの構文はextendsとabstractです。若気の至り。</font>

# Interfaceってなんぞや
Interface（いんたーふぇいす）というのは接触面、中間面を表す英単語なんだそう。（Wikipediaより）
パソコンについてるUSBなんかもパソコンと、色々な周辺機器をつなぐための<b>インターフェイス</b>なんて呼ばれますよね。
これは色々な周辺機器がそれぞれ独自のコネクタだったら接続するときにめんどくさすぎるので、USBという規格に従って共通化されているからなのですが。

そんな感じで、他のクラスと共通の入出力などをInterfaceを実装することで実現することができます。やっていこう。

# Interfaceのつくりかた
JavaでInterfaceを定義するには`interface`キーワードを使います。
Interfaceにはメンバ変数と抽象メソッドのみを定義することができます。

メンバ変数には自動的に`public static final`の扱いになるので、定数としてのみ使うことができます。

メソッドは抽象メソッドになるので、Interfaceに処理を定義することはできず、メソッドの名前・返り値・仮引数のみ定義できます。

```java:ExampleInterface.java
interface ExampleInterface{
  int getNum();
  void setNum(int num);
}
```

で、これを使うクラス側で`implements`キーワードを使って実装してあげます。
`implements`は「実装」という意味なんですって。

```java:ExampleClass.java
class ExampleClass implements ExampleInterface{
  int num = 10;

  @Override
  int getNum(){
    return num;
  }

  @Override
  void setNum(int num){
    this.num = num;
  }
}
```

前述したことの繰り返しになりますが、Interfaceに定義したメソッドは勝手に抽象メソッドになるので、必ずオーバーライドする必要があります。

こんな感じでとりあえず、今までメッチャメチャ書いてきたgetterとsetterをInterfaceにして実装してみました。

# Interfaceの便利な使い方
## キャストできる
継承したときのようにInterfaceもキャストができます。

とりあえず、適当なクラスを作りました。
Interfaceはさっきのを使います。

```java:ExampleInterface.java
interface ExampleInterface{
  int getNum();
  void setNum(int num);
}
```

適当なクラスAとBを作ります。

```java:ClassA.java
class ClassA implements ExampleInterface{
  int num = 10;

  @Override
  int getNum(){
    return num;
  }

  @Override
  void setNum(int num){
    this.num = num;
  }
}
```

```java:ClassB.java
class ClassB implements ExampleInterface{
  int num = 20;

  @Override
  int getNum(){
    return num;
  }

  @Override
  void setNum(int num){
    this.num = num;
  }
}
```

じゃあ、こいつ動かしてみますか。
Interfaceの長所を使わずに適当に出力してみます。

```java:RunClass.java
class RunClass{
  public static void main(String[] args){
    ClassA classA = new ClassA();
    ClassB classB = new ClassB();

    printNum(classA);
    printNum(classB);
  }

  static void printNum(ClassA classA){
    System.out.println(classA.getNum());
  }

  static void printNum(ClassB classB){
    System.out.println(classB.getNum());
  }
}
```

説明をわかってもらうためにだいぶめんどくさい書き方しました。
今、定義したクラスが2つしかないからいいけど、もし他にもClassCとかClassDとか増えて来たら大変ですよね。

じゃあ、<b>Interfaceの型にキャストして処理</b>してみましょう！

```java:RunClass.java
class RunClass{
  public static void main(String[] args){
    ClassA classA = new ClassA();
    ClassB classB = new ClassB();

    printNum(classA);
    printNum(classB);
  }

  static void printNum(ExampleInterface instance){
    System.out.println(instance.getNum());
  }
}
```

こんな感じで`ExampleInterface`を実装したクラスはすべて`printNum`メソッドで処理できるようになりました。

このように<b>実装したすべてのクラスで共通の名前のメソッドがあることを約束したい</b>ときに利用できるんじゃないかなと思います。

## 複数実装ができる
`extends`キーワードによる継承は2つも3つもクラスを継承することはできませんでしたが、<b>Interfaceはできます</b>。

パソコンにUSBだけじゃなくてイヤホンを挿すアナログ端子とか、LANポートがあったりしますよね。
そんな感じで、Interfaceをガシガシ追加することで、様々な入出力に対応させることができます。

なので、Interfaceはあくまでも入出力関連のメソッドを実装するのに利用し、ゴリッゴリの処理を書くのに使うべきではないと思います。

ひとつのクラスが機能を持ちすぎていると、1つのファイルに1000行を超えたりとかしてやべぇことになってしまい、どこに何を書いたかわからなくなるのでやるべきではありません。

なので、ゴリッゴリの処理を実装したいときは抽象クラスにして、また他のクラスを継承したくなったらそもそも機能を切り分けて別のクラスを作ることを考えたほうがいいでしょう。

<b>お前は○○する係な！</b>と、ひとことで言い表せるくらいがベストなんじゃないかな...？

# シメ
Interfaceと抽象クラスの使い分けは誰もが一度は直面する問題みたいなので、自分の中での最適解が見つかるまではGoogle先生と仲良くなって、Qiitaのエントリとか、なんちゃらエンジニア塾の記事を読んでみたらいいんじゃないかなって思います。

以上！

# 参考
[【Java入門】interface(インタフェース)の使い方総まとめ](https://www.sejuku.net/blog/25772)