1. ホーム
  2. language-agnostic

[解決済み】「インターフェースに合わせたプログラム」とはどういう意味ですか?

2022-03-23 20:03:17

質問

何度か目にしたことがあるのですが、意味がよくわかりません。いつ、なぜ、このようなことをするのでしょうか?

インターフェイスの役割は分かっているのですが、これがはっきりしないことで、正しい使い方ができていないのではないかと思っています。

すればいいだけなのでしょうか。

IInterface classRef = new ObjectWhatever()

を実装した任意のクラスを使用することができます。 IInterface ? どんな時にそんなことをする必要があるのでしょうか?唯一考えられるのは、あるメソッドがあり、そのメソッドに渡されるオブジェクトが IInterface . しかし、そのようなことが頻繁に起こるとは思えません。

また、あるインターフェースを実装しているオブジェクトを取り込むメソッドはどのように書けばいいのでしょうか?可能なんでしょうか?

どのように解決するのですか?

この質問に対する回答で、インターフェースやコードの疎結合、制御の逆転などについて、いろいろと詳しく書かれた素晴らしいものがあります。 かなり頭の痛い議論もあるので、なぜインターフェースが有用なのかを理解するために、この機会に少し噛み砕いて説明したいと思います。

私もインターフェイスに触れ始めたころは、その関連性に戸惑いました。 なぜインターフェースが必要なのかがわからなかったのです。 JavaやC#のような言語を使っている場合、すでに継承があるので、私はインターフェイスを、以下のように見ていました。 ある意味、私は正しかったです。インターフェースは弱い継承の一種と考えることができますが、それ以上に、潜在的に多くの非関連クラスのオブジェクトが示す共通の特性や動作を分類する手段として考えることで、ようやく言語構成としての用途を理解することができました。

例えば、SIMゲームに以下のようなクラスがあったとします。

class HouseFly inherits Insect {
    void FlyAroundYourHead(){}
    void LandOnThings(){}
}

class Telemarketer inherits Person {
    void CallDuringDinner(){}
    void ContinueTalkingWhenYouSayNo(){}
}

明らかに、この2つのオブジェクトは、直接継承という点では何の共通点もありません。 しかし、どちらも迷惑な存在と言えるかもしれません。

例えば、私たちのゲームでは、ある種のランダムな もの 夕食を食べるときにプレイヤーを困らせる。 これは HouseFly または Telemarketer またはその両方 -- しかし、1つの関数でどうやって両方を可能にするのでしょうか? また、異なるタイプのオブジェクトに、同じようにquot;do their annoying thing"を求めるにはどうしたらよいのでしょうか?

実現するための鍵は TelemarketerHouseFly は、モデルとしては何も似ていないにもかかわらず、共通の緩やかな解釈の動作を共有しています。 そこで、両者が実装可能なインタフェースを作ってみよう。

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 というインターフェイスがあります。 このように、簡単に TelemarketersHouseFlys は、それぞれの方法で迷惑をかけることになります。 DiningRoom オブジェクトは害虫であり、それが何であるかはあまり気にしませんし、他のオブジェクトと共通点がない可能性もあります。

この非常に巧妙な擬似コードの例(予想以上に長引いた)は、インターフェイスを使用する場合について、最終的に私に光を当ててくれたようなものを説明するためのものです。 馬鹿馬鹿しい例で申し訳ないのですが、理解の助けになれば幸いです。 ちなみに、ここに掲載されている他の回答は、デザインパターンや開発方法論におけるインターフェイスの使い方の範囲を網羅しています。