はじめに
今回は「Interface(表記はインターフェースで固定)」について説明します。一部厳密な説明がなされていないことをご了承ください。
インターフェースを使用するメリットは何ですか?
「インターフェース」についての質問が投げかけられた場合、どう答えるか考えてみましょう。そして、その回答にどのくらい深く踏み込めるかも考えてみてください。意外と正確な回答が難しいと感じることがありますよね?
実際に、インターフェースの使い方は最初は理解しにくく、そのメリットもよく分からないことがあります。私も含めて、きれいな回答が難しいと感じることがあったため、この記事ではインターフェースについて、もっとフランクにまとめてみました。
説明の流れ
- インターフェースの言葉の定義を知る
- インターフェースをプログラミング的観点から考える
- インターフェースの使いどころを考える
インターフェースとは
インターフェースは、継承を前提とした抽象化の手段の一つです。(なお、抽象クラスを使用する方法もありますが、今回は触れません。)一般的な説明では、「インターフェースを継承したクラスはそのインターフェースの実装を強制させられる」といった表現がありますが、この説明だけではインターフェースのメリットを十分に理解することは難しいでしょう。
こちらは公式のC#リファレンスです。また、この記事もインターフェースについて分かりやすく解説されているのでおすすめです。
多態性の定義
まず、多態性は別名「ポリモーフィズム」とも呼ばれます。オブジェクト指向プログラミングにおいて、多態性は同じメッセージ(メソッド)を異なるオブジェクトが受け取ったときに、それぞれのオブジェクトが異なる方法で応答する能力を指します。
動的多態性と静的多態性に関して
多態性には主に2つの型の解決方法があります。
- 静的な型付けにおける静的多態性(Static Polymorphism)
- 動的な型付けにおける動的多態性(Dynamic Polymorphism)
それぞれを簡単に説明します。
静的多態性は、コンパイル時に型情報を利用して関数やメソッドのオーバーロード(Overload)やジェネリックス(Generics)などを解決する方法です。コンパイラは引数の型やジェネリックスの具体化を考慮して、正しいメソッドや関数のバージョンを選択します。
動的多態性は、実行時にオブジェクトの実際の型を基にメソッドの振る舞いを決定する方法です。これは、オブジェクト指向プログラミングの中心的な概念であり、仮想関数(Virtual Function)やポリモーフィズム(Polymorphism)として知られています。
今回は特に動的多態性に焦点を当てて考えていきたいと思います。
動的多態性の実現
-
オブジェクトの多態性(Object Polymorphism)
実行時にオブジェクトの型が判明し、対応するメソッドが呼び出されます。これは、オブジェクト指向プログラミングにおける継承やインターフェースの利用によって実現されます。 -
メソッドの多態性(Method Polymorphism)
静的多態性と動的多態性の両方が存在します。
動的多態性においては実行時にどのメソッドが呼び出されるかが決定されます。オーバーライド(サブクラスで親クラスのメソッドを再定義する)がこれにあたります。オブジェクト指向言語では、動的多態性は仮想関数(virtual function)として知られる仕組みによって実現されます.
インターフェースのメリットとは
インターフェースを利用することによって得られるメリットは以下のようなものがあります。
- 抽象的な振る舞いが上位解決方法となるため、異なるクラスの型を同じ型として扱えること
- 処理パターンによって具象クラスを用意することでロジックがシンプルになる(モジュールの凝集度が高くなる)
- 条件分岐を減らせる
- 処理の取り換えが容易になる
- モジュール間を疎結合にできる
サンプルコード
インターフェースは抽象的なものとなります。(ここでは抽象インターフェースAとします)それを継承するのは具象クラスとなります。(ここでは具象クラスB・Cとします)
例えば、以下のようなサンプルコードを考えてみましょう。
public interface IShape
{
void Draw();
}
public sealed class Circle : IShape
{
public void Draw()
{
// 円の描画処理
}
}
public sealed class Rectangle : IShape
{
public void Draw()
{
// 長方形の描画処理
}
}
上記の例で言えば、「図形を描く」という概念を抽象化しています。世の中には様々な図形がありますが、この中では円や長方形の描画処理は具象クラス「Circle」「Rectangle」にそれぞれ記載されています。
この抽象化によって、図形を描く際にインターフェース「IShape」のDrawメソッドを呼び出すことで、円も長方形も同じインターフェースを通して描画処理を行うことができるのです。つまり、クライアント側からは同じ呼び出し方法で処理の切り替えが可能であり、それぞれの具象クラスの実装の詳細は具象クラスに委ねられるというメリットがあります。
理解を優先するため、コードは簡単にしてあります。
また、処理の取り換えが容易になるという点についても考えてみましょう。
外部環境やAPIの呼び出しのような不安定な処理やテスト時の再現性の低い処理は、抽象的に「~する」といった形でインターフェースに定義しておくことで、柔軟に処理を切り替えることができます。この考え方はSOLID原則の一つである「依存関係逆転の原則」に基づくもので、具象クラスに依存するのではなく、抽象クラスに依存することで処理の切り替えが容易になるのです。
最後に
今回は、多態性からインターフェースのメリットについて簡単に解説しました。インターフェースはクリーンアーキテクチャなどでも重要な役割を果たしており、さらに理解を深めるためにはSOLID原則を学習すると良いでしょう。
もし興味があれば、以下の書籍や講義も参考にしてみてください。
書籍
Clean Architecture 達人に学ぶソフトウェアの構造と設計
こちらの本はソフトウェアの設計の基本的なルールを学習できます。
- なぜアーキテクチャが必要なのか?
- プログラミングの基本的な考え方
- 設計の原則(ここでSOLID原則が登場します)
- コンポーネントの原則
このような点を抑えてからクリーンアーキテクチャとは何か?といった話につながっていきます。すべてが理解できずとも上記に挙げた4点だけを学習するだけでもいいと思います。
講義
SOLID原則であればピーコックアンダーソンさんの講義がとても分かりやすくておススメです。
オブジェクト指向の原則1:単一責務の原則とオープンクローズドの原則
オブジェクト指向の原則2:リスコフの置換原則と継承以外の解決方法
オブジェクト指向の原則3:依存関係逆転の原則とインタフェース分離の原則
参考動画
こちらはミノ駆動さんと成瀬さんの動画です。とても分かりやすく解説されてます!クリーンアーキテクチャに関してはgithubでコードをクローンしてきてコードを見ながら動画を見ると理解度が全然違うと思うのでオススメです。
以上、最後まで読んでいただきありがとうございました!