3

これは、この質問で与えられた @Peter Meyer の回答に対するフォローアップの質問です ( What does it mean to "program to an interface"? )。

最初に、これを新しい質問にするのは嫌だということから始めさせてください。しかし(私はstackoverflowが大好きですが、ここでは少し批判的でなければなりません)1)私はPeter Meyerに個人的にメッセージを送ることができませんでした(読む: within-the-stack-exchange-network )、2) 「フォローアップ」の質問を投稿できませんでした (読み取り: https://meta.stackexchange.com/questions/10243/asking-a-follow-up-question)および3)、質問は「爆発の丸薬」を避けるためにロックされていましたが、残念ながら、そこで質問するのに十分な評判がありません。

そのため、新しい質問を投稿する必要があります。

そのスレッドで、Peter Meyer は、インターフェイスをいつ使用するか、インターフェイスへのプログラミングが重要である理由について、見事で面白い例を示しました。

私の質問はこれです.ラッパークラスを使用することは、彼の問題を解決するための別のアプローチではないでしょうか?

あなたは書くことができませんでした:

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();
  }
}
class DiningRoom {

  DiningRoom(Person[] diningPeople, IPest[] pests) { ... }

  void ServeDinner() {
    when diningPeople are eating,

      foreach pest in pests
        pest.BeAnnoying();
  }
}

この上:

class IPest {
  HouseFly houseFly;
  public IPest(HouseFly houseFly) {
    this.houseFly = houseFly;
  }
  Telemarketer telemarketer;
  public IPest(Telemarketer telemarketer) {
    this.telemarketer = telemarketer;
  }
  void BeAnnoying() {
    if(houseFly != null)
      houseFly.BeAnnoying();
    else
      telemarketer.BeAnnoying();
  }
}


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

  void BeAnnoying() {
    FlyAroundYourHead();
    LandOnThings();
  }
}

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

  void BeAnnoying() {
     CallDuringDinner();
     ContinueTalkingWhenYouSayNo();
  }
}
class DiningRoom {

  DiningRoom(Person[] diningPeople, IPest[] pests) { ... }

  void ServeDinner() {
    when diningPeople are eating,
      foreach pest in pests
        pest.BeAnnoying();
  }
}

?

私はこれを言語にとらわれないものとしてタグ付けしましたが、私が最もよく知っているので、この質問を実際に「Java 化」しているので、ご容赦ください。しかし、私が見たように、インターフェイス アプローチを使用することには欠点があります。たとえば、さまざまなタイプの「toString()」メソッドをオーバーライドして、「IPest」または「HouseFly」として表されているかどうかに基づいて異なる値を返す場合、インターフェイスではそれを行うことはできません。「HouseFly」自体に、IPest インターフェースをインターフェースで実装する HouseFly の場合とは異なる toString 値を与えることはできません (HouseFly は常にクラス定義によってインターフェースを実装するため)。ラッパー クラスは、インターフェイスよりも幅広い機能を提供します。

例として、リスト内のすべての「IPest」を表示したいとしますが、害虫がハエなのかテレマーケティング担当者なのかを表示するために、リストのそれぞれに識別マークを付けたいとします。次に、ラッパー クラスを使用すると、これは簡単になります。

class IPest {
  HouseFly houseFly;
  public IPest(HouseFly houseFly) {
    this.houseFly = houseFly;
  }
  Telemarketer telemarketer;
  public IPest(Telemarketer telemarketer) {
    this.telemarketer = telemarketer;
  }
  void BeAnnoying() {
    if(houseFly != null)
      houseFly.BeAnnoying();
    else
      telemarketer.BeAnnoying();
  }
  public String toString() {
    return (houseFly == null? "(T) " + telemarketer.toString() : "(F) " + houseFly.toString()) + 
  }
}

次に、別の場所で、HouseFly を単独で (IPest ではなく HouseFly として) 表すリストがある場合は、toString() に別の値を指定できます。

これは toString() に限定されませんが、オブジェクトが IPest として表されている場合と、HouseFly または Telemarketer として表されている場合とで異なる機能を提供するためにオーバーライドしたい場合がある、これらのクラスの他のメソッドがあります。

私の質問が理にかなっていることを願っています。

私の理論では、API など、誰もが使用するものをプログラミングしている場合は、具体的なクラスを避け、インターフェイスを使用するようにしてください。しかし、クライアント コードを直接記述していて、コードの再利用の見込みがない (または可能性がない) 場合、「インターフェイスへのプログラミング」はそれほど大したことではないように思えます。

フィードバックをお待ちしております。私はここで基地外ですか?私はコードを書くのが苦手ですか? うまくいけば、Peter Meyer が意見を述べてくれます...

4

1 に答える 1

3

私にとって、これは明らかな利点がないのに、コードを非常に醜くしています。(それは私が意図したものではありません...実際の質問には+1)。

大きな欠点は、IPest クラスです。可能性のある害虫を追加し続けると、このクラスは巨大になり、未使用の変数とコードで肥大化します。30 種類の害虫がある場合、IPest クラスは 2 種類の例よりも 15 倍大きくなり、これらすべてのクラスをサポートするための追加のコードがたくさんあります。

さらに悪いことに、このコードの大部分は、実際にはインスタンス化されたオブジェクトに関連していません。IPest が HouseFly を表すと想定される場合、いくつかのインスタンス変数 (他のタイプの IPest ごとに 1 つ) がすべて空であり、大量の未使用コードがあります。さらに悪いことに、IPest に null 以外の値が複数ある場合はどうなるでしょうか。それは何ですか?(テレマーケターのブランドルフライ!)

これを、より多くのクラスが実装しても大きくならない純粋なインターフェースと比較してください (気にしないため)。

最後に、HouseFly オブジェクトや IPest オブジェクトなどの 2 つ (またはそれ以上) のオブジェクトで表される単一の概念的アイデア (単一のハエなど) を持つことは、一般的に有用 (または良い考え) ではないと思います。より多くの機能を追加したいオブジェクト。ラッパーごとに別のオブジェクトを追加します。これは、追跡して更新する可能性のある別のオブジェクトです。

これは、このようなものが良い考えではない非常に特殊なケースがあり得ないと言っているわけではありません...しかし、上記の理由により、ここでは見られません.

于 2013-05-09T17:30:14.180 に答える