インターフェイスについて最初に理解しておくべきことは、インターフェイスは継承には使用されないということです。これは非常に重要なことです。複数のクラスで同じ具体的なコードを共有しようとしている場合、それはインターフェイスの目的ではありません。
2 番目に理解しておくべきことは、クライアント コードとサービス コードの違いです。
クライアント コードは基本的に、一連のデータ要求の「最後のステップ」です。MVC のコントローラーまたはビューは、クライアント コードと見なすことができます。一方、モデルはサービスコードと見なすことができます。
インターフェイスは、クライアント コードがサービスから取得するデータの種類に一貫性を持たせることを目的としています。または、別の考え方として、インターフェイスは、サービスがクライアント コードからの要求と互換性があることを確認する方法です。それが彼らがするすべてです。複数のクラスが共有できる実装ではなく、文字通り、データにアクセスするためのインターフェイスを提供します。
具体例を挙げると:
クライアント コード - ユーザーのフォーラム プロファイルの ProfileViewController クラス
class ProfileViewController
{
public function showProfile(User $user)
{
$user->getProfile();
}
}
Service Code - データを取得し、それを要求しているクライアント コードに渡す User モデル
class User
{
public function getProfile()
{
$profile = Do some SQL query here or something
return $profile;
}
}
ここで、後でユーザーをメンバー、管理者、レフリー、モデレーター、ライター、編集者などに分割し、それぞれに独自の種類のプロファイルがあるとします。(たとえば、独自のカスタム クエリ、またはデータ、またはあなたが持っているもの)
ここには 2 つの問題があります。
- そこに渡すものには getProfile() メソッドが含まれていることを保証する必要があります。
- User オブジェクト以外を渡すと、showProfile() は失敗します。
1 は、抽象クラスとメソッド (またはインターフェイス) を使用して簡単に解決できます。2 も最初は簡単に思えます。なぜなら、モデレーター、管理者、およびメンバーをすべてユーザー基本クラスのサブクラスにすることができるからです。
しかし、その後、USER プロファイルに加えて、汎用プロファイルが必要になった場合はどうなるでしょうか。おそらく、スポーツ選手のプロフィールや有名人のプロフィールを表示したいでしょう。ユーザーではありませんが、プロファイル/詳細ページがあります。
これらはユーザーではないため、User のサブクラスと見なしても意味がない場合があります。
だから今、あなたは少し立ち往生しています。showProfile() は、User オブジェクト以上のものを受け入れることができる必要があります。実際、最終的にそこに渡したいオブジェクトのタイプはわかりません。しかし同時に、常に $user->getProfile() を取得できるようにしたいので、そこに渡すものはすべて、渡されるのに十分な汎用性が必要であり、具体的な getProfile() メソッドを実装する必要があります。
解決?インターフェイス!!!!!
最初のいくつかのサービス コード
// First define an interface for ANY service object that will have a profile
interface IHasProfile
{
public function getProfile();
}
// Next, define the class for an object that should have a profile. I'll do a bunch for the sake of an example...
class User implements IHasProfile
{
public function getProfile()
{
$profile = Your unique user profile query here
return $profile;
}
}
class Celebrity implements IHasProfile
{
public function getProfile()
{
$profile = Your unique celebrity profile query here
return $profile;
}
}
class Car implements IHasProfile
{
public function getProfile()
{
$profile = Your unique vehicle profile query goes here
return $profile;
}
}
次に、それを使用するクライアント コード
class ProfileViewController
{
public function showProfile(IHasProfile $obj)
{
$obj->getProfile();
}
}
そして、あなたはそれを持っています。showProfile() は十分に抽象化されているため、どのオブジェクトを取得するかは問題ではありません。オブジェクトが public getProfile() メソッドを持っていることのみを問題とします。これで、心ゆくまで新しいタイプのオブジェクトを作成できるようになりました。それらがプロファイルを持つことを意図している場合は、それらに「implements IHasProfile」を与えるだけで、自動的に showProfile() で動作します。
不自然な例ですが、少なくともインターフェイスの概念を説明する必要があります。
もちろん、単に「怠惰」で、オブジェクトをまったく型キャストせずに、任意のオブジェクトを渡すことができるようにすることもできます。しかし、それは完全に別のトピックです ;)