web-dev-qa-db-ja.com

クラスではなくインターフェイスからオブジェクトインスタンスを作成するのはなぜですか?

クラスから生成されたInterfaceインスタンスを何度も見ました。なぜこのようにインターフェイスを使用するのですか?インターフェイスインスタンスは、派生クラスの助けを借りて自分自身のみを作成し、このインスタンスを通じてこのインターフェイスメンバーにのみアクセスできます。これはどのように利点をもたらしますか?私は困惑している..

interface IPrint
{
    void Print();
}

class Sample : IPrint
{
    public void Print()
    {
        Console.WriteLine("Print...");
    }

    public void Sample()
    {
        Console.WriteLine("Sample...");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IPrint print = new Sample();
        print.Print();
    }
}
56
user2282567

インターフェイスは、クラスが何かを実行できなければならないことを定義します。これは、作業中のオブジェクトがあなたがしたいことをすることを知っていることを意味します。これにより、OOPの自由度と利点が広がります。これは深いトピックですが、非常に基本的な例は次のとおりです。

public interface IAnimal
{
    string Speak();
}

public class Dog : IAnimal
{
    public string Speak()
    {
        return "Woof, woof";
    }
} 

public class Cat : IAnimal
{
    public string Speak()
    {
        return "Meow";
    }
} 

public class Parrot : IAnimal
{
    public string Speak()
    {
        return "Sqwark!";
    }
} 

次に、好きな動物を使用できます!

class Program
{
    static void Main(string[] args)
    {
        // Writes Woof, Woof
        IAnimal animal = new Dog();
        Console.WriteLine(animal.Speak());        

        // Now writes Meow
        animal = new Cat();
        Console.WriteLine(animal.Speak());

        // Now writes Sqwark etc
        animal = new Parrot();
        Console.WriteLine(animal.Speak());
    }
}

これにより、Inversion Of Controlのようなこともできるようになります。ここでは、このようなアイテムを受け取り、犬、猫、またはオウムを渡すことができます。どの動物でしたか:

public void ShoutLoud(IAnimal animal)
{
    MessageBox.Show("Shout " + animal.Speak());
}

これにより、実際の動物ではなくモックオブジェクトを使用できるため、ShoutLoud nit testableになります。基本的に、堅固で密結合ではなく、コードを柔軟で動的にします。

また、マシューの質問を拡大します。 C#では、1つの基本クラスからのみ継承できますが、複数のインターフェイスを持つことができます。だから、あなたは持つことができます:

public class Dog : IAnimal, IMammal, ICarnivor

これにより、小さなインターフェイスを使用して(推奨)、構築することができるため、アイテムができること/する必要があることを最大限に制御できます。

94
Belogix

この方法でインターフェイスを使用すると、インターフェイスの標準テンプレートを使用するメソッドを作成できます。したがって、ここでは、すべてがIPrinterから継承するプリンターの多くのクラスがあるかもしれません

class SamsungPrinter : IPrinter
{
    // Stuff and interface members.
}

class SonyPrinter : IPrinter
{
    // Stuff and interface members.
}

interface IPrinter
{
    void Print();
}

したがって、各タイプSamsungPrinterSonyPrinterなどに対して、次のようなものを使用して前処理できます。

public static void PreProcessAndPrint(IPrinter printer)
{
    // Do pre-processing or something.
    printer.Print();
}

IPrinterから継承し、メソッドパラメーターでその型を使用することで、渡されるオブジェクトに対して常にPrintメソッドを安全に使用できることがわかります。

もちろん、インターフェースの使用には他にも多くの用途があります。それらの使用の一例は、設計パターン、特にファクトリーおよび戦略パターンです。その説明と例は こちら にあります。

これがお役に立てば幸いです。

8
MoonKnight

ただし、これは、たとえば仮想メソッドで基本クラスを使用する場合とどのように異なりますか?

1人のプログラマーまたは1つのプログラムがインターフェースとクラスを作成することを前提としていますが、これは常にこの方法である必要はありません。

たぶん、あなたは動物で動作する完全な完成したプログラムを持っており、これを使用してこれを解決しました:

public abstract class Animal { public abstract string Speak(); }

そして、いつかあなたは動物の写真を表示するいくつかの素晴らしいDLLをnugetからダウンロードします。クラスライブラリにはコントラクトが含まれています-インターフェイス-'IAnimal':

namespace AwesomeAnimalLibrary
{
public interface IAnimal
{
string AnimalName;
}
}

クラスライブラリには次のものも含まれる場合があります。

namespace AwesomeAnimalLibrary
{
public class AnimalPhotos
{
[Byte] GetPhotos(IAnimal animal);
}
}

あなたは今何ができますか? basクラスのAnimalは、AwesomeAnimalLibrary IAnimalインターフェイスを実装できます。

他の人が抽象基底クラスを使用するが、インターフェイスコントラクトを使用して連携することを想定しないでください。

1
Krijn

インターフェースはプロパティまたはメソッドのシグネチャのみを実装するため、インターフェースはインスタンスを持つことができません。インターフェイスは、あるクラスのインスタンスへの単なるポインタです。

interface IExample
{
   // method signature
   void MyMethod();
}
public class MyClass : IExample
{
   // method implementation
   public void MyMethod()
   {
      ConsoleWriteline("This is my method");
   }
}

// interface pointing to instance of class
IExample ie = new MyClass();
ie.MyMethod();
0
cembo