121

これは非常に基本的な質問であることを私は知っていますが、インタビュアーは非常に巧妙な方法で私に尋ねました、そして私は無力でした:(

私はインターフェースの物質的または理論的な定義しか知らず、私が取り組んだ多くのプロジェクトにもそれを実装しました。しかし、私はこれがなぜそしてどのように役立つのか本当に理解していません。

また、インターフェースの1つも理解していません。つまり、たとえば、

conn.Dispose();最後にブロックします。IDisposableしかし、クラスがinterface(SqlConnection)クラスを実装または継承していることはわかりません。メソッド名を呼び出すにはどうすればよいのでしょうか。また、同じように、Disposeメソッドがどのように機能するかを理解していません。なぜなら、すべてのインターフェイスメソッドに対して独自の実装で関数本体を実装する必要があるからです。では、インターフェースはどのように契約として受け入れられるか、名前が付けられますか?これらの質問は今まで頭に浮かび、率直に言って、自分の質問を理解できる方法で説明する良いスレッドを見たことがありませんでした。

いつものようにMSDNは非常に怖く見え、そこには1行も明確ではありません(高レベルの開発に取り組んでいる皆さん、親切な言い訳ですが、コードや記事はそれを見る人の心に届くはずです。したがって、他の多くの人が言うように、MSDN役に立たない)。

インタビュアーは言った:

彼には5つのメソッドがあり、クラスに直接実装できますが、抽象クラスまたはインターフェイスを選択する必要がある場合は、どちらを選択しますか。その理由は何ですか。抽象クラスとインターフェースの両方の長所と短所について、さまざまなブログで読んだすべてのことを彼に答えましたが、彼は確信が持てず、一般的に「なぜインターフェース」を理解しようとしています。「なぜ抽象クラス」とは、同じメソッドを1回しか実装できず、変更できない場合でも一般的です。

ネットのどこにも、インターフェイスとその機能について明確に説明する記事を入手できませんでした。私は多くのプログラマーの1人であり、インターフェイスについてはまだ知りませんが(使用した理論と方法は知っています)、それを明確に理解していることに満足していません。

4

16 に答える 16

94

次のようなものを作成する場合、インターフェイスは優れています。

using System;

namespace MyInterfaceExample
{
    public interface IMyLogInterface
    {
        //I want to have a specific method that I'll use in MyLogClass
        void WriteLog();       
    }

    public class MyClass : IMyLogInterface
    {

        public void WriteLog()
        {
            Console.Write("MyClass was Logged");
        }
    }

    public class MyOtherClass : IMyLogInterface
    {

        public void WriteLog()
        {
            Console.Write("MyOtherClass was Logged");
            Console.Write("And I Logged it different, than MyClass");
        }
    }

    public class MyLogClass
    {
        //I created a WriteLog method where I can pass as a parameter any object that implements IMyLogInterface.
        public static void WriteLog(IMyLogInterface myLogObject)
        {
            myLogObject.WriteLog(); //So I can use WriteLog here.
        }
    }

    public class MyMainClass
    {
        public void DoSomething()
        {
            MyClass aClass = new MyClass();
            MyOtherClass otherClass = new MyOtherClass();

            MyLogClass.WriteLog(aClass);//MyClass can log, and have his own implementation
            MyLogClass.WriteLog(otherClass); //As MyOtherClass also have his own implementation on how to log.
        }
    }
}

私の例では、私はを書く開発者MyLogClassであり、他の開発者はクラスを作成することができ、ログに記録したいときに、インターフェースを実装することができますIMyLogInterfaceWriteLog()でメソッドを使用するために何を実装する必要があるかを彼らが私に尋ねていたのと同じですMyLogClass。彼らがインターフェースで見つける答え。

于 2012-06-06T13:30:58.200 に答える
54

インターフェイスを使用する理由の1つは、コードの柔軟性が向上するためです。次のように、クラスタイプAccountのオブジェクトをパラメータとして受け取るメソッドがあるとします。

public void DoSomething(Account account) {
  // Do awesome stuff here.
}

これに伴う問題は、メソッドパラメータがアカウントの実装に向けて固定されていることです。他の種類のアカウントが必要ない場合は、これで問題ありません。この例では、代わりにアカウントインターフェイスをパラメータとして使用しています。

public void DoSomething(IAccount account) {
  // Do awesome stuff here.
}

このソリューションは実装に固定されていません。つまり、SuperSavingsAccountまたはExclusiveAccount(両方ともIAccountインターフェイスを実装)を渡して、実装されたアカウントごとに異なる動作を取得できます。

于 2016-03-08T12:45:07.333 に答える
49

インターフェイスは、実装者が従わなければならないコントラクトです。抽象クラスは、コントラクトと共有実装を許可します。これは、インターフェイスでは不可能なことです。クラスは、複数のインターフェースを実装および継承できます。クラスは、単一の抽象クラスのみを拡張できます。

なぜインターフェースなのか

  • デフォルトまたは共有コードの実装はありません
  • データ契約(Webサービス、SOA)を共有したい
  • インターフェイスの実装者ごとに異なる実装があります(IDbCommand特定SqlCommandOracleCommand方法でインターフェイスを実装しています
  • 多重継承をサポートしたい。

なぜ抽象的か

于 2012-06-06T13:14:24.423 に答える
25

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

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

インターフェイスは、オブジェクトが相互に何も知る必要なしに連携するために使用できるコントラクトを提供するため、便利です。

于 2017-08-25T12:18:08.320 に答える
23

一言で言えば-ポリモーフィズムのために!

「実装ではなくインターフェイスにプログラムする」場合は、同じインターフェイス(タイプ)を共有するさまざまなオブジェクトを引数としてメソッドに挿入できます。このように、メソッドコードは別のクラスの実装と結合されません。つまり、同じインターフェイスの新しく作成されたオブジェクトを操作するために常に開いています。(オープン/クローズ原則)

  • 依存性注入を調べて、デザインパターン-GOFによる再利用可能なオブジェクト指向ソフトウェアの要素を確実に読んでください。
于 2013-11-27T23:09:08.487 に答える
6

この質問をすることですでに多くの血がこぼれていると思います。そして多くの人が、普通の人間には理解できないロボットのような用語を説明することによってこの問題を解決しようとしています。

だから最初に。なぜインターフェースとなぜ抽象的であるかを学ぶには、それらが何のためにあるのかを学ぶ必要があります。ファクトリクラスを適用するときに、私はこの2つを個人的に学びました。あなたはこのリンクで良いtuturialを見つけます

さて、私がすでに与えたリンクに基づいて掘り下げましょう。

ユーザーの要件(トラックタンク飛行機などの追加など)に応じて変更される可能性のある車両クラスがあります。

public class clsBike:IChoice
{
   #region IChoice Members
    public string Buy()
    {
       return ("You choose Bike");
    }
    #endregion
}

public class clsCar:IChoice
{
   #region IChoice Members
    public string Buy()
    {
       return ("You choose Car");
    }
    #endregion
}

両方とも、MyClassにBuyメソッドが必要であると単純に言うContractIChoiceがあります

public interface IChoice
{
    string Buy();
}

ご覧のとおり、そのインターフェイスはメソッドを強制するだけですBuy()が、継承されたクラスがメソッドを実装するときに何をするかを決定します。これはインターフェイスの制限です。純粋にインターフェイスを使用すると、abstactを使用して自動的に実装できるタスクを繰り返すことになります。この例では、各車両の購入には割引があります。

public abstract class Choice
{
    public abstract string Discount { get; }
    public abstract string Type { get; }
    public string Buy()
    {
       return "You buy" + Type + " with " + Discount;
}
public class clsBike: Choice
{
    public abstract string Discount { get { return "10% Discount Off"; } }
    public abstract string Type { get { return "Bike"; } }
}

public class clsCar:Choice
{
    public abstract string Discount { get { return " $15K Less"; } }
    public abstract string Type { get { return "Car"; } }
}

これでファクトリクラスを使用して同じことを実現できますが、抽象を使用する場合は、基本クラスにメソッドを実行させますBuy()

まとめ:インターフェイスコントラクトは継承クラスに実装を行わせ、抽象クラスコントラクトは実装を初期化できます(継承クラスによってオーバーライドできます)

于 2015-11-11T12:51:34.983 に答える
4

C#にはダックタイピングがありません-特定のメソッドが一連の具象クラスに実装されていることを知っているからといって、そのメソッドの呼び出しに関してそれらをすべて同じように扱うことができるとは限りません。インターフェイスを実装すると、そのインターフェイスが何を定義するかに関して、それを実装するすべてのクラスを同じタイプのものとして扱うことができます。

于 2012-06-06T13:12:17.907 に答える
3

これは簡単な例です。

との両方がインターフェースArrayList実装しますIList。以下にastring[]とaがあり、 IListList<string>を使用して1つのメソッドのみで両方を操作します。

string[] myArray = { "zero", "one", "two", "three", "four"};
List<string> myList = new List<string>{ "zero", "one", "two", "three"};

//a methode that manipulates both of our collections with IList
static void CheckForDigit(IList collection, string digit)
{
    Console.Write(collection.Contains(digit));  //checks if the collection has a specific digit
    Console.Write("----");
    Console.WriteLine(collection.ToString()); //writes the type of collection
}

static void Main()
{
    CheckForDigit(myArray, "one");   //True----System.String[]
    CheckForDigit(myList, "one");   //True----System.Collections.Generic.List`1[System.String]



//Another test:

    CheckForDigit(myArray, "four");   //True----System.String[]
    CheckForDigit(myList, "four");   //false----System.Collections.Generic.List`1[System.String]
}
于 2019-01-17T13:34:43.980 に答える
2

インターフェイスを使用すると、次のことができます。

1)実装のさまざまなカットを提供する分離されたインターフェースを作成し、よりまとまりのあるインターフェースを可能にします。

2)インターフェース間で同じ名前の複数のメソッドを許可します。これは、競合する実装がなく、署名だけであるためです。

3)実装とは関係なく、インターフェースをバージョン管理してハイブオフし、契約が確実に満たされるようにすることができます。

4)コードは、具体化ではなく抽象化に依存できるため、テストモックなどの注入を含むスマートな依存性注入が可能になります。

私が確信している理由は他にもたくさんありますが、これらはほんの数例です。

抽象クラスを使用すると、部分的に具体的なベースを使用できます。これはインターフェイスと同じではありませんが、テンプレートメソッドパターンを使用して部分的な実装を作成する機能など、独自の品質を備えています。

于 2012-06-06T13:15:20.457 に答える
2

インターフェースは、現実(オブジェクト)の抽象化(クラス)の抽象化(原型)を作成することです。

インターフェースは、クラスによって提供される実装を提供せずに契約条件を指定することです。

インターフェイスは仕様です。

  • インターフェースは、それが単独で静的であるため、概念の不動の振る舞いを指定するための設計時のアーティファクトです。

  • クラスは、現実が相互作用して移動するときに現実のモバイル構造を指定するための実装時のアーティファクトです。

インターフェイスとは何ですか?

猫を観察すると、4本の足、頭、体幹、尾、髪の毛を持った動物であると言えます。彼が歩いたり、走ったり、食べたり、ニャーと鳴いたりできることがわかります。等々。

これで、プロパティと操作を使用してインターフェイスを定義しました。そのため、手口は定義していませんが、機能がどのように機能するかを知らずに機能と機能のみを定義しています。つまり、機能と区別を定義しています。

そのため、UMLではこれをクラス図でクラスと呼んでいますが、実際にはまだクラスではありません。これは、プライベートと保護されたメンバーを定義して、アーティファクトの詳細を把握できるようにするためです。UMLでは、インターフェイスはC#のインターフェイスとは少し異なるため、ここで混同しないでください。これは、抽象化アトムへの部分的なアクセスポイントのようなものです。そのため、クラスは複数のインターフェイスを実装できると述べました。C#のインターフェイスは、抽象化を抽象化し、この抽象化をアクセスポイントとして制限するために使用されるため、同じことですが、そうではありません。それは2つの異なる用途です。したがって、UMLのクラスは、プログラミングクラスへの完全な結合インターフェイスを表しますが、UMLインターフェイスは、プログラミングクラスのセクションのデカップリングインターフェイスを表します。それはそう、UMLのクラス図は実装を処理せず、そのすべてのアーティファクトはプログラミングインターフェイスレベルにあります。UMLクラスをプログラミングクラスにマッピングしますが、これは抽象抽象化から具体的な抽象化への転置です。デザインの分野とプログラミングの分野の間の二分法を説明する微妙な点があります。したがって、UMLのクラスは、プログラミングインターフェイスの観点からは、内部の隠されたものを考慮したプログラミングクラスです。

インターフェースは、厄介な方法で利用できない場合に多重継承をシミュレートすることもできます。たとえば、catクラスは、animalインターフェイスから派生するcatインターフェイスを実装します。この猫のクラスは、歩く、走る、食べる、音を出すなどのインターフェースも実装します。これは、クラスレベルでの多重継承の欠如を補いますが、すべてを再実装する必要があるたびに、現実自体が行うように、せいぜい現実を因数分解することはできません。

ユニット内でインターフェースと実装セクションを定義するPascalオブジェクトコーディングを参照できることを理解するため。インターフェイスでタイプを定義し、実装でタイプを実装します。

unit UnitName;

interface

type
  TheClass = class
  public
    procedure TheMethod;
  end;

implementation

class procedure TheClass.TheMethod;
begin
end;

ここで、インターフェースセクションはUMLクラスの設計に一致しますが、インターフェースタイプは他のものです。

したがって、私たちのビジネスでは、2つの異なるが類似したものを指名するために、1つの単語、インターフェースがあり、それは混乱の原因です。

また、たとえばC#では、プログラミングインターフェイスを使用すると、強く型付けされたハビリティを失ったため、目標を実際に成功させることなく、オープン型に真のジェネリックポリモーフィズムがないことを補うことができます。

結局のところ、(分散)共通オブジェクトモデルで導入されたように、互換性のないシステムがメモリ内のオブジェクトの実装と管理について心配することなく通信できるようにするために、インターフェイスが必要です。

クラスとは何ですか?

外部の観点から現実の縮小を定義した後、内部の観点からそれを説明できます。これは、カプセル化した現実を実現し、感謝を相互作用させるためのデータ処理とメッセージ管理を定義するクラスです。インスタンスを使用してオブジェクトに。

したがって、UMLでは、機械のホイールへのフラクタルな没入を実現し、状態や相互作用などを記述して、処理したい現実の断片の抽象化を実装できるようにします。

そのため、抽象クラスは、コンパイラーの観点からは、インターフェースと同等です。

詳しくは

プロトコル(オブジェクト指向プログラミング)

C#-インターフェイス

C#-クラス

于 2019-09-30T19:16:46.850 に答える
1

抽象クラスとインターフェースはどちらもコントラクトです。

コントラクトの考え方は、いくつかの動作を指定することです。実装したと言う場合は、契約に同意したことになります。

インターフェースよりも抽象の選択はです。

抽象クラスの非抽象子孫は、コントラクトを実装します。

インターフェイスを実装するクラスはすべて、コントラクトを実装します。

したがって、すべての子孫が実装する必要のある動作を指定する場合は抽象を使用し、個別のインターフェイスを定義する必要がありますが、この効果的に集約されたコントラクトを満たすものはすべて子孫である必要があります。

于 2012-06-06T13:28:03.067 に答える
1

1つの抽象クラスからのみ継承できます。複数のインターフェースから継承できます。これにより、ほとんどの場合に何を使用するかが決まります。

抽象クラスの利点は、基本実装を持つことができることです。ただし、IDisposableの場合、基本クラスは適切にクリーンアップする方法を知らないため、デフォルトの実装は役に立ちません。したがって、インターフェースの方が適しています。

于 2012-06-06T13:14:20.863 に答える
1

フライングトースターについてお話ししましょう。

フライングトースター

もちろん、インターフェイスを宣言したり実装したりせずに、動作するソフトウェアシステムを構築できる状況はたくさんあります。オブジェクト指向のソフトウェア設計は、クラスだけを使用して実現できます。

繰り返しになりますが、任意のソフトウェアシステムをアセンブリ言語で実装することもできますが、マシンコードで実装することもできます。抽象化メカニズムを使用する理由は、抽象化メカニズムが物事を容易にする傾向があるためです。インターフェイスはそのような抽象化メカニズムです。

したがって、インターフェイスを使用すると実装が非常に簡単な特定の重要なオブジェクト指向設計があり、そのような場合にはインターフェイスが実際に必要になります。

これらの重要な設計は、多重継承と関係があります。これは、「真の」形式では、クラスが1つの基本クラスだけでなく、2つ以上の基本クラスから継承する場合です。この真の形式はC#では不可能ですが、C#やJavaなどの言語が登場する前は、支配されていた言語はC ++でした。これは、真の多重継承を完全にサポートしています。残念ながら、真の多重継承は言語の設計を非常に複雑にし、有名な「菱形継承問題」などのさまざまな問題を引き起こすため、あまり良い考えではないことが判明しました。(J Francisによる「多重継承の正確な問題は何ですか?」を参照してください)

したがって、誰かが「フライングトースター」クラスを作成したい場合は、既存の「トースター」クラスと既存の「フライング」クラスから継承します。彼らが遭遇する可能性が高い種類の問題は、トースタークラスの電源が壁のコンセントである可能性があり、フライングマシンクラスの電源が鳩の餌である可能性があり、結果として生じる新しいクラスはどちらかであるということでしたどういうわけか両方を持っているか、どちらを持っているかは不明です。(菱形継承問題。)

C#やJavaのような言語の作成者は、言語を単純に保ち、菱形継承問題のような落とし穴を避けるために、真の多重継承を許可しないことに決めました。ただし、何らかの形の多重継承が依然として必要である(または少なくとも非常に望ましい)ため、これらの言語では、真の多重継承の問題と複雑さを回避しながら、より少ない形式の多重継承をサポートする手段としてインターフェイスを導入しました。

このより少ない形式の多重継承では、複数の基本クラスから継承するクラスを持つことは許可されていませんが、少なくとも1つ以上のインターフェースから継承することはできます。したがって、フライングトースターを作成する場合、既存のトースタークラスと既存のフライングクラスの両方から継承することはできませんが、既存のトースタークラスから継承し、自分で実装したフライングインターフェイスを公開することもできます。トースターからすでに継承している手段を使用している可能性があります。

したがって、2つの異なる無関係な機能のセットを集約するクラスを作成する必要性を感じない限り、多重継承の形式は必要ありません。したがって、インターフェイスを宣言または実装する必要はありません。

于 2019-11-02T12:52:25.597 に答える
0

インターフェイスを使用すると、クラス設計者はエンドユーザーが利用できるメソッドを非常に明確にすることができます。それらはまた、ポリモーフィズムの不可欠な部分です。

于 2012-06-06T13:10:40.667 に答える
0

抽象クラスに対するインターフェースの定義は投稿しません。理論をよく知っていると思いますし、SOLIDの原則を知っていると思いますので、実用的にしましょう。

ご存知のように、インターフェースにはコードを含めることができないため、欠点は非常に簡単に理解できます。

コンストラクターを提供するクラスのプロパティを初期化する必要がある場合、または実装の一部を提供する場合は、抽象クラスが、それを実行できないインターフェイスに適しています。

したがって、非常に一般的には、クラスを継承/拡張するコンストラクターまたはコードをクライアントに提供する必要がある場合は、インターフェースよりも抽象クラスを優先する必要があります。

于 2012-06-06T13:14:13.077 に答える
-2

抽象クラスは関連するエンティティ用に作成されますが、インターフェイスは関連しないエンティティに使用できます。

たとえば、AnimalとHumanという2つのエンティティがある場合は、Interfaceに移動します。詳細に移動する必要がある場合は、Tiger、lionと言い、Animalと関連付けたい場合は、AnimalAbstractクラスを選択します。

以下のようになります

   Interface             
   ____|____
  |        |
Animal   Human



  Animal (Abstract class)
   __|___
  |      |
Tiger   Lion
于 2013-11-27T14:06:16.347 に答える