2

これは、この質問のフォローアップ質問です。

次のような継承ツリーがあるとします。

Car -> Ford -> Mustang -> MustangGT

これらのクラスごとにインターフェイスを定義することには利点がありますか?例:

ICar -> IFord -> IMustang -> IMustangGT

おそらく他のクラス(のようなChevy)が実装したいと思うIcarかもしれませんし、おそらくそうIFordかもしれませんIMustangが、おそらくIMustangGTそれがそれほど具体的であるためではありません。この場合、インターフェースは不要ですか?

また、実装したいクラスは、コードが重複しないように、IFordから継承して1つの継承を使用したいと思うでしょう。Fordそれが与えられた場合、実装することの利点は何IFordですか?

4

14 に答える 14

16

私の経験では、インターフェイスは、それぞれが同じメソッドに応答する必要がある複数のクラスがある場合に最適に使用されます。これにより、それらのクラスの共通インターフェイスに対して記述される他のコードと互換的に使用できます。インターフェイスの最適な使用法は、プロトコルが重要であるが、基礎となるロジックがクラスごとに異なる場合です。そうでなければロジックを複製する場合は、代わりに抽象クラスまたは標準クラスの継承を検討してください。

そして、あなたの質問の最初の部分に答えて、私はあなたのクラスごとにインターフェースを作成することをお勧めしません。これにより、クラス構造が不必要に乱雑になります。インターフェイスが必要な場合は、後でいつでも追加できます。お役に立てれば!

アダム

于 2008-11-06T13:40:55.043 に答える
6

また、特定のメソッドに応答する必要があるクラスによってインターフェイスを共有する必要があるというadamalexの応答にも同意します。

クラスが同様の機能を持っているが、祖先の関係で互いに直接関連していない場合、インターフェイスは、2つの間で機能を複製することなくその機能をクラスに追加するための良い方法です。(または、微妙な違いだけで複数の実装があります。)

車の例えを使用している間、具体的な例です。次のクラスがあるとしましょう。

Car -> Ford   -> Escape  -> EscapeHybrid
Car -> Toyota -> Corolla -> CorollaHybrid

車は持っているwheelsし、できるDrive()し、Steer()。したがって、これらのメソッドはCarクラスに存在する必要があります。(おそらく、Carクラスは抽象クラスになります。)

線を下ると、との違いがわかりますFordToyotaおそらく、車のエンブレムのタイプの違いとして実装され、おそらく抽象クラスです)。

そして最後に、完全に自動車として実装されたクラスであるEscapeCorollaクラスがあります。

さて、どうすればハイブリッド車を作ることができるでしょうか?

メソッドを追加するサブクラスと、メソッドEscapeを持つサブクラスを作成できます。メソッドは基本的に同じことをしますが、それでも異なるメソッドがあります。うん。それよりもうまくやれるようです。EscapeHybridFordsHybridDrive()CorollaCorollaHybridToyotasHybridDrive()

ハイブリッドには方法があるとしましょうHybridDrive()。(完璧な世界で)2つの異なるタイプのハイブリッドを作成したくないのでIHybrid、メソッドを持つインターフェースを作成できますHybridDrive()

したがって、またはクラスを作成する場合は、EscapeHybridCorollaHybridインターフェイス実装するIHybridだけです。

実際の例として、Javaを見てみましょう。オブジェクトと別のオブジェクトの比較を実行できるクラスは、Comparableインターフェースを実装します。名前が示すように、インターフェースは比較可能なクラス用である必要があるため、 「Comparable」という名前になります。

興味深いことに、Javaチュートリアルのインターフェイスレッスンでは車の例が使用されています。

于 2008-11-06T14:24:53.237 に答える
2

私はあなたが参照する必要があるもののためのインターフェースを作るだけだと思います。あなたは車について知る必要がある他のいくつかのクラスや機能を持っているかもしれませんが、フォードについて知る必要がある何かがどれくらいの頻度でありますか?

于 2008-11-06T13:40:56.803 に答える
2

不要なものを作成しないでください。インターフェイスが必要であることが判明した場合は、戻ってそれらを構築するのは簡単な作業です。

また、衒学者の側では、この階層のようなものを実際に構築していないことを願っています。これは、継承が使用されるべきものではありません。

于 2008-11-06T13:41:59.393 に答える
2

そのレベルの機能が必要になったときにのみ作成してください。

コードのリファクタリングは常に進行中のプロセスです。

必要に応じてインターフェイスに抽出できるツールが利用可能です。EG http://geekswithblogs.net/JaySmith/archive/2008/02/27/refactor-visual-studio-extract-interface.aspx

于 2008-11-06T13:48:39.253 に答える
1

ICarとその他すべて(Make = Ford、Model = Mustangなど)を、インターフェイスを実装するクラスのメンバーとして作成します。

あなたはあなたのフォードクラスと例えばGMクラスを持ちたいかもしれません、そしてあなたがチェックのルートをたどりたくないならポリモーフィズムを使うために両方ともICarを実装しますMake == Whatever、それはあなたのスタイル次第です。

とにかく-私の意見では、これらは車の属性であり、その逆ではありません-メソッドが一般的であるため、必要なインターフェイスは1つだけです:ブレーキ、スピードアップなど。

フォードは他の車ができないことをすることができますか?私はそうは思わない。

于 2008-11-06T13:50:46.643 に答える
0

私の見解では、インターフェースは、クラスが特定の署名、または(私が思うように)特定の「動作」を実装するという要件を強制するためのツールです。人称代名詞。インターフェイスに名前を付けて、そのように読み取れるようにします... ICanFly、IKnowHowToPersistMyself IAmDisplayableなど...したがって、この例では、特定の完全なパブリック署名をミラーリングするためのインターフェイスを作成しません。クラス。公開署名(動作)を分析してから、メンバーを(例を使用して)IMove、IUseFuel、ICarryPassengers、ISteerable、IAccelerate、IDepreciateなどの小さな論理グループ(小さいほど良い)に分割します。私のシステムの他のクラスへのそれらのインターフェースはそれらを必要とします

于 2008-11-06T14:25:03.313 に答える
0

最初の2つのレベル、ICarとIFordを作成し、2番目のレベルのインターフェイスが必要になるまで2番目のレベルをそのままにしておきます。

于 2008-11-06T13:39:24.890 に答える
0

問題のドメイン内でオブジェクトが互いにどのように相互作用する必要があるかを慎重に検討し、特定の抽象的な概念の複数の実装が必要かどうかを検討してください。インターフェイスを使用して、他のオブジェクトが相互作用する概念に関するコントラクトを提供します。

あなたの例では、FordはおそらくManufacturerであり、MustangはManufacturer Fordによって使用されるModelName値であると提案します。したがって、次のようなものがあります。

IVehichle-> CarImpl、MotorbikeImpl-持っている-メーカーが持っている-多くのModelNames

于 2008-11-06T13:57:43.790 に答える
0

インターフェイスとクラスの違いに関するこの回答では、次のように説明しました。

  • インターフェイスは、概念何であるかを公開し (コンパイル時に「何が」有効かという点で)、に使用されます(MyInterface x = ...)
  • クラスは、概念何をするか(実行時に実際に実行される) を公開し、値またはオブジェクト (MyClass x または aMyClass.method() ) に使用されます。

したがって、Ford のさまざまなサブクラスを「Ford」変数 (「値」の概念) に格納する必要がある場合は、IFord を作成します。それ以外の場合は、実際に必要になるまで気にしないでください。

それは 1 つの基準です。それが満たされない場合、IFord はおそらく役に立たないでしょう。
それが満たされている場合、前の回答で明らかにされた他の基準が適用されます。Ford が Car よりも豊富な API を持っている場合、IFord はポリモーフィズムの目的に役立ちます。そうでない場合は、ICar で十分です。

于 2008-11-06T14:05:02.420 に答える
0

インターフェースは一般的なパブリック API であることを意図しており、ユーザーはこのパブリック API の使用に制限されます。ユーザーが のタイプ固有のメソッドを使用することを意図していない限りIMustangGT、インターフェイス階層をICarおよびに制限することをお勧めしますIExpensiveCar

于 2008-11-06T14:33:08.867 に答える
0

一般に、これ (およびオブジェクト指向に関する多くの質問) について考える最良の方法は、コントラクトの概念について考えることです。

契約は、2 つ (またはそれ以上) の当事者間の合意として定義され、各当事者が満たさなければならない特定の義務を規定します。プログラムでは、これはクラスが提供するサービスであり、サービスを取得するためにクラスに提供する必要があるものです。インターフェイスは、インターフェイスを実装するすべてのクラスが満たす必要がある契約を示します。

ただし、それを念頭に置いて、あなたの質問は、使用している言語と何をしたいかによって多少異なります。

何年にもわたってオブジェクト指向を行ってきた (なんてことだ、30 年間) 後、私は通常、特に Java で、すべてのコントラクトのインターフェイスを作成します。これにより、テストが非常に簡単になるからです。オブジェクトを簡単に、ほとんど簡単にモックできます。

于 2008-11-06T14:28:32.777 に答える
-1

インターフェイスと抽象クラスからのみ継承します。

ほぼ同じクラスがいくつかあり、メソッドの大部分を実装する必要がある場合は、他のオブジェクトを購入することと組み合わせて、インターフェイスを使用します。
Mustangクラスが非常に異なる場合は、インターフェイスICarだけでなく、IMustangも作成します。
したがって、クラスFordとMustangはICarから継承でき、MustangとMustangGTはICarIMustangから継承できます。

クラスFordを実装し、メソッドがMustangと同じである場合は、Mustangから購入します。

class Ford{
  public function Foo(){
    ...
    Mustang mustang  = new Mustang();
    return mustang.Foo();
}
于 2008-11-06T13:49:57.863 に答える