これについては何度か言及されているのを目にしましたが、それが何を意味するのかよく分かりません。いつ、なぜこれを行うのでしょうか?
インターフェースが何をするのかはわかっていますが、この点を明確に理解していないため、インターフェースを正しく使用していないのではないかと考えています。
次のようにすれば、まさにそうなるでしょうか:
IInterface classRef = new ObjectWhatever()
を実装する任意のクラスを使用できますかIInterface
? いつそれを行う必要がありますか? 私が考えられる唯一のことは、メソッドがあり、それを実装すること以外にどのオブジェクトが渡されるかわからない場合ですIInterface
。 どのくらいの頻度でそれを行う必要があるのかわかりません。
また、インターフェースを実装するオブジェクトを受け取るメソッドをどのように記述すればよいでしょうか? それは可能ですか?
ベストアンサー1
この質問に対する素晴らしい回答がここにいくつかあり、インターフェースや疎結合コード、制御の反転などについて、さまざまな詳細が説明されています。かなり難しい議論もあるので、この機会にインターフェースがなぜ役立つのかを理解するために、少し詳しく説明したいと思います。
私も、初めてインターフェースに触れたときは、その関連性について混乱していました。インターフェースがなぜ必要なのか理解できませんでした。Java や C# などの言語を使用している場合は、すでに継承が存在し、インターフェースは継承の弱い形式であると考えて、「なぜわざわざ?」と考えていました。ある意味では私の考えは正しかったです。インターフェースは継承の弱い形式であると考えることができますが、それ以上に、インターフェースを、潜在的に多くの関連のないオブジェクト クラスが示す共通の特性や動作を分類する手段と考えることで、言語構成要素としてのインターフェースの使用法をようやく理解しました。
たとえば、SIM ゲームがあり、次のクラスがあるとします。
class HouseFly inherits Insect {
void FlyAroundYourHead(){}
void LandOnThings(){}
}
class Telemarketer inherits Person {
void CallDuringDinner(){}
void ContinueTalkingWhenYouSayNo(){}
}
明らかに、これら 2 つのオブジェクトは直接継承という点では共通点がありません。しかし、どちらも厄介だと言えるでしょう。
たとえば、ゲーム プレイヤーが夕食を食べるときに、何らかのランダムな要素HouseFly
がゲームに必要だとします。これはまたはTelemarketer
、あるいはその両方である可能性がありますが、1 つの関数でその両方を実現するにはどうすればよいでしょうか。また、異なる種類のオブジェクトそれぞれに、同じように「迷惑なこと」をさせるにはどうすればよいでしょうか。
重要なのは、 とTelemarketer
はHouseFly
、モデリングの点ではまったく似ていないにもかかわらず、どちらも緩く解釈される共通の動作を共有しているということです。そこで、両方が実装できるインターフェースを作成しましょう。
interface IPest {
void BeAnnoying();
}
class HouseFly inherits Insect implements IPest {
void FlyAroundYourHead(){}
void LandOnThings(){}
void BeAnnoying() {
FlyAroundYourHead();
LandOnThings();
}
}
class Telemarketer inherits Person implements IPest {
void CallDuringDinner(){}
void ContinueTalkingWhenYouSayNo(){}
void BeAnnoying() {
CallDuringDinner();
ContinueTalkingWhenYouSayNo();
}
}
これで、それぞれ独自の方法で厄介な 2 つのクラスができました。また、同じ基本クラスから派生して共通の固有の特性を共有する必要はありませんIPest
。単に の契約を満たす必要があります。その契約は単純です。 を実行するだけですBeAnnoying
。この点で、次のようにモデル化できます。
class DiningRoom {
DiningRoom(Person[] diningPeople, IPest[] pests) { ... }
void ServeDinner() {
when diningPeople are eating,
foreach pest in pests
pest.BeAnnoying();
}
}
ここでは、多数の食事客と多数の害虫を受け入れるダイニング ルームがあります。インターフェイスの使用に注意してください。これは、この小さな世界では、配列のメンバーが実際にはオブジェクトまたはオブジェクトpests
である可能性があることを意味します。Telemarketer
HouseFly
このServeDinner
メソッドは、夕食が提供され、ダイニングルームの人々が食事をするはずのときに呼び出されます。私たちの小さなゲームでは、そのときが害虫が働くときです。各害虫は、IPest
インターフェースを介して迷惑になるように指示されます。このように、両方を簡単に用意してTelemarketers
、HouseFlys
それぞれの方法で迷惑にすることができます。オブジェクトにDiningRoom
害虫が含まれていることだけを気にし、それが何であるかは気にしません。また、害虫が他の害虫と共通点がなくてもかまいません。
この非常に不自然な疑似コードの例 (予想よりもずっと長くなりましたが) は、インターフェイスをいつ使用するかについて、最終的に私の目から光が射すようなことを説明することを目的としています。例が馬鹿げていることをあらかじめお詫びしますが、理解の一助になれば幸いです。また、確かに、ここで受け取った他の投稿された回答は、今日のデザイン パターンと開発方法論におけるインターフェイスの使用の全範囲を実際にカバーしています。