Interfaceクラスの使い方ポイント解説【オブジェクト指向】

#はじめに#
オブジェクト指向設計の中でも理解の難しい要素の一つ、Interfaceクラスについて使い方のポイントを解説します。
オブジェクト指向特有の難解な言葉は使わず**「どんなメリットがあるか」**に絞って解説しますので、初学者の方に読んで頂けると嬉しいです。

#Interfaceクラスとは#
あるクラスが提供する**機能の使い方のみ**を定義したクラスです。
Interfaceの名前の通り、境界として**外のクラスからどう見えるか**だけを定義しており、一切のデータ、処理を持ちません。
データ、処理を持たないクラスなので、当然そのまま使うことはできません。
Interfaceクラスを使うには、Interfaceの使い方を実現したクラスをインスタンス化して使用します。
![Interface.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506949/325ef5ff-53f3-890c-1e9e-776c06b3c8d7.png)
一見デメリットしか感じないInterfaceクラスですが、一体どんなメリットがあるのか？
２つのメリットを解説していきます。

#メリット①中身を入れ替えられる#
先ほどInterfaceクラスはそのままでは使えず、使い方を実現したクラスをインスタンス化して使用する、と書きました。
これが何を意味するかというと、**中身が固定されず、入れ替えることができる**ということになります。
クラス図で見てみましょう。
![①-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506949/88c0d80e-751e-3976-3b2b-034a0bad654c.png)
UserAクラスはIPartsクラスを参照し、実現クラスであるArmクラスのインスタンス化はPartsFactoryクラスが行います。
UserAクラスから見たIPartsクラスはMoveメソッドが見えるだけですが、Moveメソッドが何を動かすかは実現クラスを入れ替えることで切り替えられます。
この場合ではArmクラスが実現クラスなので、「腕を動かす」という動作になります。

これに新たなパーツを追加するとどうなるでしょう？
足パーツを追加した場合のクラス図は以下のようになります。
![①-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506949/89816177-e691-cbfc-440e-b85c38a0d1a0.png)
新しくLegクラスが追加され、PartsFactoryクラスが生成する対象が増えました。
これにより、PartsFactoryクラスがArmクラスを生成した場合は「腕を動かす」、Legクラスを生成した場合は「足を動かす」動作をすることになります。
しかし、UserAクラスと既存のArmクラスは何も変更しません。つまり、**パーツの追加が既存の機能に悪影響を与えることが絶対にない**ことが保証できるということになります。
これにより、オブジェクト指向の目的である**高い拡張性**を実現しています。

また、既存のパーツクラスに不具合があり、修正した場合も、他の機能に悪影響を与えることはありません。
この仕組みは、同時に**高い保守性**も実現していることになります。

ちなみにこれが、オブジェクト指向本に出てくる**オープン・クローズドの原則**というものです。
このクラスの組み合わせはデザインパターンの**Strategyパターン**です。
「あーあれってそういうことか！」と頭の回路が繋がったなら幸いです。:grinning:

#メリット➁見せたい面だけを見せる#
Interfaceクラスを使うことにより、一つのクラスに複数の側面を持たせることができます。
これが何を意味するかというと、相手に**見せたい側面だけを切り出して見せることができる**ということになります。
同じ人でも仕事とプライベートでは違う顔を見せる、という風に考えると分かりやすいかと思います。
クラス図で見てみましょう。
![➁-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506949/92f35f01-e9a4-5abd-578f-e11b76cd6bc1.png)
EmployeeCostクラスはISalalyクラスとITaxクラスのメソッドを実現しています。
ISalalyクラスとITaxクラスはそれぞれ別のUserA、Bクラスから参照されていますが、UserA、BクラスにはEmployeeCostクラスの一部しか見えていません。

もし税金計算に変更があり、EmployeeCostクラスのCalcTaxメソッドが変更された場合、影響範囲は以下の図の青色のクラスになります。
![➁-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506949/336a6e13-8abb-0570-f975-da48bcc01239.png)
CalcTaxメソッドはITaxクラスの定義なので、UserBには影響します。
一方、ISalalyクラスの定義には何も変更がないので、UserAには影響がありません。

つまり、Interfaceを分割することで、**片方のinterfaceが変更されても、もう一方には影響しない**ことが保証できるということになります。
この仕組みも**保守性**と**拡張性**の向上に役立っています。

ちなみにこれが、オブジェクト指向本に出てくる**インターフェース分離の原則**というものです。
これも「あーそうか！」となったでしょうか？

#Interfaceの重要性#
オブジェクト指向の三要素といえばカプセル化、継承、ポリモーフィズム(多態性）ですが、最近の流れとして継承を除外する傾向にあるようです。現に、最近の言語であるGoやRustなどでは言語機能として継承をサポートしていないとのこと。
（これは私の推測ですが）継承はあまりに強力すぎる機能で、オブジェクト指向が目指すシンプルで閉じた設計に反するプログラムを沢山生み出す原因となったため、いっそ存在しない方が良いと判断されたのだと思っています。この流れには私も賛成です。

継承がない環境でポリモーフィズム(多態性）を実現するにはどうするか？
そこで重要性を増すのがInterfaceクラスです。

**オブジェクト指向はInterfaceに対してプログラミングする**の格言が示す通り、オブジェクト指向の根幹はInterfaceを駆使した疎結合の実現と考えています。
是非Interfaceクラスを使いこなし、Coolな設計をしてください。:grin:

#まとめ#
・Interfaceクラスとは**機能の使い方のみ**を定義したクラス
・中身の入れ替えられるという特性により、**高い拡張性**を実現する（保守性もね）
・複数の側面を持たせられるという特性により、**高い保守性**を実現する（拡張性もね）
・継承を避ける最近の傾向により、Interfaceクラスの重要性は高まっている

最後まで読んで頂き、ありがとうございました！！