【PHP】interfaceとabstractの違い

# interface
`interface`という英語の意味は「接点」や「境界面」といった意味で、ニュアンスでいうと「異なる２つのものを仲介する」といった感じ。
### 構文と使い方
```php:構文
interface 名前
{
  public function 抽象メソッド名();
}
```
ちなみに、interfaceをクラスで使用するときは「継承」とは言わず「実装」って言うらしい。

```php:使い方
interface LifeStyle
{
  //定数を定義できる
  const $feeling = happy;
  
  //実装を伴うメソッドやプロパティの定義はできない(抽象メソッド)
  public function breakfast();
  public function lunch();
  public function dinner();
  public function greeting($message);
}

//implementsで使用
class Taro implements LifeStyle 
{
  public function breakfast()
  {
    echo '食パン';
  }
  
  public function lunch()
  {
    echo 'うどん';
  }
  
  public function dinner()
  {
    echo 'お好み焼き';
  }
  
  public functino greeting($message)
  {
    echo $message;
  }
}
```

### 特徴
> 1. 定数を定義できる
> 2. アクセス修飾子は`public`のみ指定可能 
> 3. interfaceはクラスじゃないからインスタンス化できない
> 4. クラスで使うときは`implements`でinterface名を指定する
> 5. 実装を伴うメソッドやプロパティの定義はできない(抽象メソッドのみ)
> 6. １つのクラスに対し複数のinterfaceを実装できる(多重継承みたいなことができる)
> 7. **`interface`で定義したメソッドをクラス内で必ず使用(オーバーライド)しなければならない**

個人的に便利だなと思うところは7番の部分。
もしinterfaceで定義してあるメソッドをクラス内で全て使わなかった場合はphpが停止するから早期エラー発見につながる。
しかも、interfaceの中で定義されているメソッドを覗くと継承元のクラスの仕様書みたいな使い方もできちゃう。

あ、ちなみに継承でおなじみ`extends`を使って、interfaceを継承してinterfaceを定義できるよ(ややこしい)。

```php:interfaceの継承
interface Human
{
  public function speak();
}

interface Japanese extends Human
{
  public function eatNatto();
}
```

# abstract
`abstract`は英語で「抽象的な」って意味。その意味の通りプログラミングの世界では「抽象クラス」って言われます(ちなみに英語で言う時もabstract classって言う)。

### 構文と使い方
```php:構文
abstract class 抽象クラス名
{
    // 抽象メソッド
    abstract アクセス修飾子 function メソッド名();
}
```
抽象クラスは書き方がちょっとややこしいので説明をば。
抽象クラスは元をたどればクラスなので抽象メソッド(処理内容が書いてないメソッド)だけじゃなくて普通のメソッドやプロパティも定義できる。
`abstract`って最初に書けばそれは「抽象〜」って呼ばれる、って覚えとけばいい多分。

でも、下に書いたような「抽象プロパティ」だけは存在できない。仲間はずれ。

```php:
//これを抽象クラス内に書いたらエラー
abstract public $value;
//これは普通のプロパティなので抽象クラス内でもOK
public $value;
```
使い方はクラスの継承と一緒で`extends`を使う。

```php:使い方
abstract class Product
{
  abstract public function sell();
}

//クラスの継承のやり方と一緒
class FoodProduct extends Product
{
  public function sell()
  {
    echo `毎度ありがとうございます`;
  }
}
```
### 特徴
> 1. アクセス修飾子は自由につけられる
> 2. 抽象プロパティだけ抽象クラスの中で定義できない
> 3. 抽象クラスはクラスだけど直接インスタンス化できない
> 4. クラスで使うときは普通の継承のように`extends`を使う
> 5. 普通のクラスみたいに中身があるメソッドやプロパティを定義できる
> 6. **抽象クラスで「定義し、なおかつ未実装のメソッド」を継承したクラス内で必ず使用(オーバーライド)しなければならない**

聡明な皆様はお気付きになるでしょう。「interfaceと一緒で定義したメソッドをクラス内で使わなきゃいけないんだったら、普通のメソッドもクラスに継承できる抽象クラスの方がいいんじゃね」と。

## [結論] interfaceとabstract(抽象クラス)の違いって？
機能的な違いは、「普通のメソッドとプロパティを定義できるかどうか」。
ここだけ見れば「interfaceいらないかも？」となってしまいます。私もそうでした。interfaceの抽象メソッドは`public`だけだし変数は定数だけですしね。

使い方での違いは二つを差別化しているようにとれます。

- **interfaceは不特定のクラスで共通のメソッドを定義したいとき。**
- **abstract(抽象クラス)は（普通のクラスを継承する立ち位置と似ていて）、共通処理の中に一部違う処理が入るとき。**


## 参考
▷[インターフェイス](https://www.php.net/manual/ja/language.oop5.interfaces.php)
▷[PHPのinterfaceとabstractを正しく理解して使い分けたいぞー](https://havelog.ayumusato.com/develop/php/e166-php-interface-abstract.html)
▷[PHPのinterfaceとは何か](http://blog.tojiru.net/article/377526320.html)
▷[Interface,Implementsを使う利点って何？【PHPのInterface】](http://togattti.hateblo.jp/entry/2013/04/30/062523)
▷[PHP Interfaces and Abstract Classes（インターフェースと抽象クラス）](http://blog.justoneplanet.info/2009/05/06/php-interfaces-and-abstract-classes%EF%BC%88%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E3%81%A8%E6%8A%BD%E8%B1%A1%E3%82%AF%E3%83%A9%E3%82%B9%EF%BC%89/)