インターフェイスが便利なのはなぜですか?


158

しばらくの間、C#で勉強とコーディングを行ってきました。しかし、それでも、インターフェイスの有用性を理解することはできません。テーブルに持っていくものが少なすぎます。機能の署名を提供する以外、何もしません。実装する必要のある関数の名前と署名を覚えていれば、それらは不要です。これらは、インターフェイス内の上記の関数が継承クラスに実装されていることを確認するためだけにあります。

C#は優れた言語ですが、Microsoftが最初に問題を作成し(多重継承を許可しない)、解決策を提供するという感覚を与えることがありますが、これは面倒なものです。

それは限られたコーディング経験に基づく私の理解です。インターフェースについてどう思いますか?どのくらいの頻度でそれらを使用しますか?


55
「実装する必要がある関数の名前と署名を覚えていれば、それらは不要です。」この声明では、静的型付け言語の利点をもう少し調べる必要があると思われます
スティーブンジュリス

37
C#を忘れ、Javaを忘れ、言語を忘れます。オブジェクト指向の観点から考えているだけです。ロバート・C・マーティン、マーティン・ファウラー、マイケル・フェザーズ、ギャング・オブ・フォーなどの人々から読み物を手に入れることをお勧めします。
アンソニーペグラム

27
インターフェースの利点を本当に理解するには、2年以上かかりました。私の提案:デザインパターンを研究する。それらのほとんどはインターフェースに依存しているため、なぜそれらが非常に役立つのかをすぐに理解できます。
オリバーワイラー

37
あなたは友達を学ぶことがたくさんあります。
ChaosPandion

60
@ChaosPandion私たちはすべて学ぶべきことがたくさんあります
ケンワーナー

回答:


151

これらは、(インターフェイス内の)上記の関数が継承クラスに実装されていることを確認するためだけにあります。

正しい。これは、機能を正当化するのに十分素晴らしい利点です。他の人が言ったように、インターフェイスは特定のメソッド、プロパティ、イベントを実装する契約上の義務です。静的型付け言語の魅力的な利点は、コンパイラが、コードが依存する契約が実際に満たされていることを確認できることです。

そうは言っても、インターフェースは契約上の義務を表すにはかなり弱い方法です。契約上の義務を表現するためのより強力で柔軟な方法が必要な場合は、Visual Studioの最新バージョンに同梱されているコードコントラクト機能を調べてください。

C#は優れた言語ですが、Microsoftが最初に問題を作成し(多重継承を許可しない)、解決策を提供するという感覚を与えることがありますが、これは面倒なものです。

まあ私はあなたがそれを好きうれしいです。

複雑なソフトウェア設計はすべて、競合する機能を相互に比較検討し、小さなコストで大きなメリットをもたらす「スイートスポット」を見つけようとする結果です。実装の共有目的として複数の継承許可する言語には、メリットが比較的少なく、コストが比較的高いことが痛い経験からわかっています。実装の詳細を共有しないインターフェイスでのみ多重継承を許可すると、ほとんどのコストなしで多重継承の多くの利点が得られます。


「Microsoftは多重継承を許可しないことで問題を引き起こします」と読んでいたのですが、エリックリッパートがそれについて何か言いたいことがあると思いました。
コンフィギュレー

この回答に関連性が高い:エリック、あなたは質問者にコード契約を紹介していますが、それらはひどく不完全です。最も基本的な契約以外は、静的チェッカーによって強制できません。小さなプロジェクトでコードコントラクトを使用してみました。入力および出力に関するすべてのことを指定するメソッドごとに何百行も追加しましたAssumeが、配列や列挙メンバーなどの場合、非常に多くの呼び出しを追加する必要がありました。すべてを追加し、静的に検証された混乱を確認した後、プロジェクトの品質が低下したため、ソース管理に戻りました。
コンフィギュレー

17
@configurator:完了できないため、不完全です。任意の契約による静的プログラム検証は、停止問題の解決と同等です。(たとえば、メソッドへの引数はFermatの最終定理の反例でなければならないというコードコントラクトを記述できますが、静的検証者はそのような引数がないことを検証することはできません。)宇宙の熱死の前に静的検証者がその作業を完了することを期待する場合、賢明にそれを使用するようになりました。(BCLの注釈が不十分であるという苦情がある場合:私は同意します。)
エリックリッパー

2
1つのメソッドが結果の配列または列挙にnullを含まないことを約束する場合、usingメソッドはnullを許可しない場所で値を使用できることを理解することを期待しています。それは私が期待していたことでしたが、そうしなかったのです。それなしでは使用できないほど重要でした。それ以外は単なるボーナスです。そうは言っても、静的検証は完全ではないことを知っています。そのため、契約に頼るのは良い選択肢ではないと思います。
コンフィギュレー

9
+1「あなたがそれを気に入ってくれてうれしい」そして、他のすべてのものも。
ロバートS.

235

ここに画像の説明を入力してください

そのため、この例では、PowerSocketは他のオブジェクトについて他に何も知りません。オブジェクトはすべてPowerSocketが提供するPowerに依存しているため、IPowerPlugを実装し、その中に接続できます。

インターフェースは、オブジェクトが相互に他のことを何も知らなくても一緒に動作するために使用できるコントラクトを提供するため、便利です。


4
左下のオブジェクトは、IPowerPlug =)を実装しているようには見えません
スティーブンストライガ

100
くそー、しかし、さまざまな国でIPowerPlugを使用するには、アダプターパターンを使用する必要があります。
スティーブンジュリス

インターフェースを回避するためにデバイスをジェリーリギングすることは安全ではありません(ただし、一部の人々はパフォーマンスをテストされていない言い訳として引用することがよくあります)。
ヤングジョン

4
この答えは驚くべきものです...
マリオガルシア

この答えを指摘するだけでは、この特定の例では、継承よりもインターフェイスを使用する方が望ましいとは言えません。インターフェイスを初めて使用する人は、すべてのプラグ機能を提供するMainsPoweredDeviceから継承するだけではなく、ソケットがMainsPoweredDeviceから派生したものをすべて受け入れる理由を尋ねる場合があります。
component_15939

145

機能の署名を提供する以外、何もしません。実装する必要がある関数の名前と署名を覚えていれば、それらは不要です

インターフェースのポイントは、どのメソッドを実装するかを思い出すのを助けることではなく、コントラクト定義することです。foreach P.Brian.Mackey例(その間違っていることが判明し、私たちは気にしない)、IEnumerableをはの間の契約を定義しますforeach任意の列挙可能なものを。「あなたが誰であれ、契約に固執している限り(IEnumerableを実装)、すべての要素を反復処理することを約束します」。そして、それは素晴らしいです(非動的言語の場合)。

インターフェイスのおかげで、2つのクラス間の結合を非常に低く抑えることができます。



「ダックタイピング」という言葉を使うのは嫌いです。なぜなら、それは人によって異なることを意味するからです。「foreach」ループにはパターンマッチングを使用します。これは、設計時にIEnumerable <T>が使用できなかったためです。C#型システムは弱すぎて必要な「モナドパターン」をキャプチャできないため、LINQにはパターンマッチングを使用します。Haskell型システムのようなものが必要です。
エリックリッパー

@Eric:「パターンマッチング」にも同じ問題はありませんか?聞いたら、F#/ Scala / Haskellだと思う。しかし、それはアヒルのタイピングよりも幅広いアイデアだと思います。
ダニエル

@ダニエル:ええ、そうだと思います。私は推測する他の6つ1つ半の6つ!
エリックリッパー

36

インターフェースは、十分に分離された構成を維持するための最良の方法です。

テストを書くとき、具象クラスがテスト環境で機能しないことがわかります。

例:データアクセスサービスクラスに依存するクラスをテストします。そのクラスがWebサービスまたはデータベースと通信している場合、単体テストはテスト環境で実行されません(さらに統合テストになりました)。

解決?クラスをユニットとしてテストできるように、データアクセスサービスのインターフェイスを使用し、そのインターフェイスをモックします。

一方、WPFとSilverlightは、バインドに関してはインターフェイスとまったく連携しません。これはかなり厄介なしわです。


2
聞いて聞いて!インターフェースは、ポリモーフィズムなどの他の問題を解決するために発明されました。ただし、私にとっては、依存性注入パターンを実装するときに独自になります。
アンディ

29

インターフェースは(静的な)ポリモーフィズムのバックボーンです!重要なのはインターフェイスです。サブクラスは基本的に、既に実装されている親のインターフェイスを継承するため、継承はインターフェイスなしでは機能しません。

どのくらいの頻度でそれらを使用し、何がそうするのですか?

かなり頻繁に。プラグ可能にする必要があるものはすべて、私のアプリケーションのインターフェースです。多くの場合、同じ振る舞いを提供する必要のある他の関係のないクラスがあります。継承ではこのような問題を解決できません。

同じデータに対して操作を実行するために異なるアルゴリズムが必要ですか?インターフェースを使用してください(戦略パターンを参照)!

異なるリスト実装を使用しますか?インターフェイスと呼び出し元に対するコードは、実装について心配する必要はありません!

単一の理由から、インターフェースに対してコーディングすることは(OOPだけでなく)良い習慣と考えられています:ニーズに合わないことに気付いたときに実装を変更するのは簡単です。多重継承だけでそれを達成しようとするか、必要なインターフェースを提供するために空のクラスを作成することに要約すると、かなり面倒です。


1
多態性を聞いたことがない、あなたは多態性を意味しますか?
スティーブンジュリス

1
Microsoftが最初の場所で多重継承を許可している場合それは言われて、インターフェースが存在する理由がなかっただろう
パンカジUpadhyay

10
@Pankaj Upadhyay:多重継承とインターフェースは2つの異なる靴の組み合わせです。動作が異なる2つの無関係なクラスのインターフェイスが必要な場合はどうなりますか?多重継承によってそれを解決することはできません。とにかく個別に実装する必要があります。そして、多態的な振る舞いを提供するために、インターフェースを説明するものが必要になります。多重継承は多くの場合、歩くのに盲目的な路地であり、遅かれ早かれ自分自身を足で撃つことはあまりにも簡単です。
ファルコン

1
簡単にしましょう。インターフェイスにDisplayとCommentの2つの関数が実装されていて、それらを実装するクラスがある場合。次に、インターフェイスを削除して、関数を直接使用してみませんか。私が言っているのは、実装する必要がある関数の名前を提供しているだけだということです。1は、これらの機能を覚えることができるなら、なぜインターフェイスを作成
パンカジUpadhyay

9
@Pankaj、それだけでインターフェースが必要な場合は、使用しないでください。クラスのすべての側面を知らないようにし、そのベースタイプ、つまりインターフェイスでアクセスしたいプログラムがある場合、インターフェイスを使用します。彼らはサブクラスを知る必要はなく、インターフェースのタイプであるというだけです。そのため、オブジェクトのインターフェイスへの参照を介して、サブクラスの実装されたメソッドを呼び出すことができます。これは基本的な継承と設計です。それがなければ、Cを使用することもできます。明示的に使用しなくても、フレームワークはCなしでは機能しません。
ジョナサンヘンソン

12

おそらくこれを使用foreachし、非常に有用な反復ツールであることがわかりました。IEnumerableが機能するにはインターフェイスが必要であることをご存知ですか?

それは確かに、インターフェースの有用性を示す具体的なケースです。


5
実際、foreachはIEnumerableを必要としません:msdn.microsoft.com/en-us/library/9yb8xew9%28VS.80%29.aspx
マットH

1
私はすべてを研究しましたが、それはもう片方の手で耳を保持するようなものです。複数の継承が許可されている場合、インターフェイスは遠い選択でした。
Pankaj Upadhyay

2
インターフェイスは多重継承であり、忘れられがちです。ただし、動作と状態の多重継承は許可されていません。ミックスインまたは特性は、動作の複数の継承を許可しますが、問題を引き起こす共有状態は許可しません:en.wikipedia.org/wiki/Mixin
Matt H

@ Pankaj、offtopic、しかしあなたの母国語が何であるかを尋ねてもいいですか?「もう一方の手で耳をかざす」というのは素晴らしいイディオムで、どこから来たのか興味がありました。
ケビン

3
@アイスマン。笑...私はインド出身です。そして、これは簡単なことを難しい方法で行うことを反映する一般的なイディオムです。
Pankaj Upadhyay

11

インターフェースは、プラグが家庭用配線にあるように、オブジェクトをコーディングします。ラジオを家の配線に直接はんだ付けしますか?あなたの掃除機はどうですか?もちろん違います。プラグとプラグが収まるコンセントは、家の配線とそこからの電力を必要とするデバイスとの間の「インターフェース」を形成します。家の配線は、3極接地プラグを使用し、120VAC <= 15Aの電力を必要とすること以外、デバイスについて何も知る必要はありません。逆に、このデバイスは、120VAC <= 15Aを提供する便利な場所に1つ以上の3極コンセントがあること以外は、家の配線方法についての不可解な知識を必要としません。

インターフェイスは、コード内で非常によく似た機能を実行します。オブジェクトは、特定の変数、パラメーター、または戻り値の型がインターフェイス型であることを宣言できます。インターフェイスをnewキーワードで直接インスタンス化することはできませんが、私のオブジェクトは、動作する必要のあるインターフェイスの実装を指定または検索できます。オブジェクトが依存関係を持つと、その依存関係を正確に知る必要はなく、依存関係でメソッドX、Y、およびZを呼び出すことができることを知るだけです。インターフェースの実装は、それらがどのように使用されるかを知る必要はなく、メソッドX、Y、およびZに特定の署名を提供することが期待されることを知る必要があります。

したがって、同じインターフェースの背後にある複数のオブジェクトを抽象化することにより、そのインターフェースのオブジェクトのコンシューマーに共通の機能セットを提供します。オブジェクトが、たとえば、リスト、辞書、LinkedList、OrderedListなどであることを知る必要はありません。これらはすべてIEnumerablesであることがわかっているため、IEnumerableのメソッドを使用して、これらのコレクションの各要素を一度に1つずつ調べることができます。出力クラスがConsoleWriter、FileWriter、NetworkStreamWriter、または他のタイプのライターを使用するMulticastWriterであることを知る必要はありません。知っておく必要があるのは、それらがすべてIWriter(または何でも)であるため、文字列を渡すことができる「書き込み」メソッドがあり、その文字列が出力されることです。


7

プログラマーが(少なくとも最初は)多重継承を持っていることは明らかですが、これはほとんど取るに足らない省略であり、(ほとんどの場合)多重継承に依存すべきではありません。この理由は複雑ですが、それについて本当に学びたい場合は、それをサポートする2つの最も有名な(TIOBE indexによる)プログラミング言語の経験を考慮してください:C ++とPython(それぞれ3番目と8番目)。

Pythonでは、多重継承がサポートされていますが、プログラマーによってほぼ普遍的に誤解されており、それがどのように機能するかを知っていると述べることは、トピック「メソッド解決順序」に関するこのペーパーを読んで理解することを意味します。Pythonで起こった他のことは、インターフェイスが言語にちょっとしたものである-Zope.Interfacesです。

C ++の場合、「ダイヤモンド階層C ++」をグーグルで検索し、これから説明するさを見てください。C ++のプロは、多重継承の使用方法を知っています。他の人は通常、結果がどうなるかを知らずに遊んでいます。インターフェースの有用性を示すもう1つのことは、多くの場合、クラスが親の動作を完全にオーバーライドする必要があるという事実です。このような場合、親の実装は不要であり、子クラスに親のプライベート変数のメモリを負担するだけです。これは、C#時代では重要ではないかもしれませんが、埋め込みプログラミングを行うときに重要です。インターフェイスを使用する場合、その問題は存在しません。

結論として、インターフェイスは契約を強制するため、私の意見では、インターフェイスはOOPの重要な部分です。多重継承は限られた場合に役立ちますが、通常は多重継承を使用する方法を知っている人だけに役立ちます。したがって、初心者の場合、あなたは多重継承の欠如によって扱われている人です-これは間違いを犯さないより良い機会を与えます。

また、歴史的に、インターフェイスのアイデアは、MicrosoftのC#設計仕様よりもはるかに早い時期に定着しました。ほとんどの人は、C#は(ほとんどの意味で)Javaのアップグレードであると考えており、C#がJavaからインターフェイスを取得した場所を推測しています。プロトコルは同じ概念の古い言葉であり、.NETよりもずっと古いものです。

更新:別の質問に答えたかもしれません-インターフェースではなく多重継承を使用する理由ですが、これはあなたが探していた答えのように見えました。OO言語には少なくとも2つのうちの1つが必要であり、他の答えは元の質問をカバーしています。


6

インターフェイスを使用せずに、クリーンでオブジェクト指向のC#コードを想像するのは困難です。クラスに特定の基本クラスからの継承を強制せずに特定の機能の可用性を適用したい場合はいつでもそれらを使用します。これにより、コードに関連レベルの(低)結合を持たせることができます。

多重継承にはそれ自身の苦痛が伴うと主張する前に、多重継承がインターフェースを持つよりも優れていることに同意しません。インターフェースは、ポリモーフィズムとコードの再利用を可能にするための基本的なツールです。さらに何が必要ですか?


5

私は個人的に抽象クラスを愛し、それをインターフェース以上に使用しています。主な違いは、IDisposable、IEnumerableなどの.NETインターフェイスとの統合、およびCOM相互運用機能との統合にあります。また、インターフェイスは抽象クラスよりも作成する労力が少し少なく、クラスは複数のインターフェイスを実装できますが、1つのクラスからしか継承できません。

そうは言っても、インターフェイスを使用するほとんどの場合は、抽象クラスを使用する方が適切です。純粋な仮想関数(抽象関数)を使用すると、インターフェイスが実装者にすべてのメンバーの定義を強制する方法と同様に、実装者に関数の定義を強制できます。

ただし、スーパークラスに特定のデザインを課したくない場合は通常、インターフェイスを使用しますが、抽象クラスを使用して、すでにほとんど実装されている再利用可能なデザインを使用します。

System.ComponentModel名前空間を使用してプラグイン環境を作成するインターフェイスを広範囲に使用しました。彼らは非常に便利です。


1
とてもいい!抽象クラスに関する私の記事を気に入っていただけると思います。抽象化がすべてです。
スティーブンジュリス

5

私はそれに関連すると言うことができます。OOとC#について初めて学び始めたとき、私もインターフェイスを取得しませんでした。それで大丈夫です。インターフェースの便利さを評価するようなものに出会うだけです。

2つのアプローチを試してみましょう。そして、一般化を許してください。

試す1

あなたは英語を母国語としています。英語が母国語ではない別の国に行きます。助けが必要です。あなたはあなたを助けることができる誰かが必要です。

「ねえ、あなたはアメリカで生まれましたか?」と尋ねますか?これは継承です。

または「ねえ、あなたは英語を話しますか」と尋ねますか?これはインターフェースです。

それが何をするのかを気にするなら、インターフェイスに頼ることができます。何であるかを気にする場合、継承に依存します。

継承に依存しても構いません。英語を話し、お茶が好きで、サッカーが好きな人が必要な場合は、ブリットを頼むほうがいいでしょう。:)

2を試す

OK、別の例を試してみましょう。

さまざまなデータベースを使用し、それらを操作するには抽象クラスを実装する必要があります。DBベンダーからのクラスにクラスを渡します。

public abstract class SuperDatabaseHelper
{
   void Connect (string User, string Password)
}

public abstract class HiperDatabaseHelper
{
   void Connect (string Password, string User)
}

多重継承ですか?上記のケースで試してみてください。できません。コンパイラは、どのConnectメソッドを呼び出そうとしているかを知りません。

interface ISuperDatabaseHelper
{
  void Connect (string User, string Password)
}

interface IHiperDatabaseHelper
{
   void Connect (string Password, string User)
}

これで、少なくともC#で-明示的にインターフェイスを実装できる、作業できるものがあります。

public class MyDatabaseHelper : ISuperDatabaseHelper, IHiperDatabaseHelper
{
   IHiperDataBaseHelper.Connect(string Password, string User)
   {
      //
   }

   ISuperDataBaseHelper.Connect(string User, string Password)
   {
      //
   }

}

結論

例は最適ではありませんが、私はそれがポイントを得ると思います。

インターフェイスの必要性を感じたときにのみ、インターフェイスを「取得」します。彼らまであなたは彼らがあなたのためではないと思うでしょう。


最初の試行は、私の投票を与えたものです。
osundblad

1
私はこれから完全にアメリカ人と英語のスピーカーのアナロジーを使用しています。すごいですね。
ブライアンベッチャー

より簡単な方法で説明しました!素晴らしい。
エイマル・カーン

4

2つの主な理由があります。

  1. 多重継承の欠如。1つの基本クラスから継承し、任意の数のインターフェイスを実装できます。.NETで多重継承を「実行」する唯一の方法です。
  2. COMの相互運用性。「古い」テクノロジーで使用する必要のあるものはすべて、インターフェースを定義する必要があります。

ポイント1が間違いなく理由であり、Microsoft開発者自身が開発した理由
Pankaj Upadhyay

1
@Pankja実際、彼らはJavaからインターフェースのアイデアを取り入れました(C#の機能の大部分のように)。
オリバーワイラー

3

インターフェイスを使用すると、システムの分離が維持されるため、リファクタリング、変更、および再デプロイが容易になります。これは、オブジェクト指向の正統性にとって非常に中核的な概念であり、C ++の達人がインターフェースとまったく同じ「純粋な抽象クラス」を作成したときに初めて学びました。


デカップリングは、システムのさまざまなコンポーネントが互いに独立しているため重要です。1つのコンポーネントに大きな影響を与える変更であっても、他のコンポーネントには波及しません。電源プラグは、電力会社へのインターフェースと考えてください(電圧とプラグの物理ピンとフォーマットを指定します)。このインターフェイスのおかげで、ユーティリティは電力の生成方法を完全に変更できます(たとえば、ソーラーテクノロジーを使用)が、どのデバイスも変更はもちろんのこと、気づくことさえありません。
miraculixx

3

インターフェース自体はあまり有用ではありません。しかし、具象クラスで実装すると、1つ以上の実装を持つ柔軟性が得られることがわかります。ボーナスは、インターフェースを使用するオブジェクトが実際の実装の詳細がどのように進むかを知る必要がないことです-これはカプセル化と呼ばれます。


2

主にコードの再利用に使用されます。インターフェイスにコーディングする場合は、そのインターフェイスから継承し、すべてを壊さない異なるクラスを使用できます。

また、クラスが何をするのかをクライアントに知らせたい(それを消費できるようにする)が、実際のコードを提供したくないWebサービスでは非常に便利です。


2

若いプログラマー/開発者として、C#を学習するだけではインターフェイスの有用性が見えないかもしれません。クラスを使用してコードを書くことができ、コードは正常に機能しますが、実際のシナリオでは、インターフェイスを使用することによってのみ可能になるいくつかのアーキテクチャとパターンは、例として依存性注入です。


1

実際の実装:

オブジェクトをインターフェイスタイプとしてキャストできます。

IHelper h = (IHelper)o;
h.HelperMethod();

インターフェースのリストを作成できます

List<IHelper> HelperList = new List<IHelper>();

これらのオブジェクトを使用すると、任意のインターフェイスメソッドまたはプロパティにアクセスできます。この方法で、プログラムの一部のインターフェイスを定義できます。そして、その周りにロジックを構築します。その後、他の誰かが自分のビジネスオブジェクトにインターフェイスを実装できます。BOが変更された場合、インターフェイスコンポーネントのロジックを変更でき、ピースのロジックを変更する必要はありません。


0

インターフェイスは、システムが配信する特定の種類のメッセージをクラスが理解する(およびサブスクライブする)メカニズムを提供することにより、プラグインスタイルのモジュール性に役立ちます。詳しく説明します。

アプリケーションでは、フォームがロードまたはリロードされるたびに、フォームがホストするすべてのものをクリアすることを決定します。IClearを実装するインターフェイスを定義しますClear。さらに、ユーザーが保存ボタンを押すたびに、フォームはその状態を保持しようとすることを決定します。ISaveそのため、従うすべてのものは、その状態を維持するためのメッセージを受け取ります。もちろん、実際には、ほとんどのインターフェイスはいくつかのメッセージを処理します。

インターフェースを際立たせるのは、継承せずに共通の動作を実現できることです。特定のインターフェイスを実装するクラスは、コマンドが発行されたときの動作(コマンドメッセージ)または照会されたときの応答方法(クエリメッセージ)を単に理解します。基本的に、アプリケーションのクラスは、アプリケーションが提供するメッセージを理解します。これにより、物を差し込むことができるモジュール式システムを簡単に構築できます。

ほとんどの言語には、インターフェイスに準拠するものを照会するためのメカニズム(LINQなど)があります。これは通常、条件付きロジックを排除するのに役立ちます。これは、(同じ継承チェーンから派生する必要のない)異なるものに、特定のメッセージに応じて同様に動作する方法を伝える必要がないためです。代わりに、特定のメッセージを理解するすべてのものを収集し(インターフェースを使用)、メッセージを公開します。

たとえば、置き換えることができます...

Me.PublishDate.Clear()
Me.Subject.Clear()
Me.Body.Clear()

... with:

For Each ctl As IClear In Me.Controls.OfType(Of IClear)()
    ctl.Clear()
Next

これは事実上次のように聞こえます:

聞いて、聞いて!クリアを理解している皆さん、Clear今すぐお願いします!

このようにして、すべてのものに自分自身をクリアするように指示することをプログラムで回避できます。そして、将来的にクリア可能なアイテムが追加されると、追加のコードなしで単純に応答します。


0

以下は擬似コードです。

class MyClass{

    private MyInterface = new MyInterfaceImplementationB();

    // Code using Thingy 

}

interface MyInterface{

    myMethod();

}

class MyInterfaceImplementationA{ myMethod(){ // method implementation A } }

class MyInterfaceImplementationB{ myMethod(){ // method implementation B } }

class MyInterfaceImplementationC{ myMethod(){ // method implementation C } }

最後のクラスは、完全に異なる実装にすることができます。

多重継承が可能でない限り、継承は親クラスの実装を課し、物事をより厳格にします。一方、インターフェイスに対するプログラミングでは、コードまたはフレームワークを非常に柔軟にすることができます。継承チェーン内のクラスを交換したい場合に出くわすと、その理由がわかります。

たとえば、もともとディスクからデータを読み取ることを目的としたReaderを提供するフレームワークを再実装して、まったく同じ性質でまったく異なる方法を実行することができます。たとえば、モールス信号を解釈します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.