5

あなたと一つ話し合う必要があります。私は、クラスがインターフェイスのすべてのメソッドの実装を提供するクラスとインターフェイスの間の契約であるというインターフェイスについて読んでいます。有名なダイヤモンド問題を解決するために、インターフェイスがあります。いいね(私はC#を使用しています)

public interface IAInterface
{
     void aMethod();
}

public interface IBInterface
{
     void aMethod();
}

public class aClass : IAInterface, IBInterface
{
     public void aMethod()
     {

     }
}    

上記のコードにより、aClass はインターフェースの両方のメソッドの実装を提供したと言われています。私の混乱は次のとおりです。それがクラスとインターフェースの間の契約である場合、両方のインターフェースとの契約が満たされているとどのように言えますか?

現実世界の例として、私がジャックと 5 ドルを同時に与えるという契約を結んでいるように、ベンと 5 ドルを与えるという契約を結んでいます。 ) 両方との契約を履行したとどのように言えますか?

私の質問は幼稚に思えるかもしれませんが、それは私をとても混乱させます。

4

7 に答える 7

11

インターフェイスは、特定のメソッド セットが実装されることを保証します。インターフェイス自体は、コードがどのように実装されるかには関与しません。クラスを拡張するのとは対照的に、クラスを拡張するときは、定義済みのコードを使用しています。

たとえば、同じメソッドで 2 つのクラスを拡張し、methodAこのメソッドを呼び出すと、コンパイラはどちらを実行する必要があるかわかりません。一方、同じメソッドで 2 つのインターフェイスを実装する場合、実装は独自のコード内に記述されるため、コンパイラは実装を見つけるためにどこに行く必要があるかを認識します。

基本的に、何かを実装すると、何らかのサービスを提供することが保証されます。

編集:私はあなたの例を取り、オブジェクト指向の方法でそれを変えようとします。これはうまくいけば、物事をより明確にするでしょう。

ジャックとベンはあなたにお金を貸すことを保証しますが、あなたはそれを返すことを保証します。

public interface IPay
{
    public void Pay(Individual i);
}

public class MySelf : IPay
{
    public void Pay(Individual i)
    {
        ...
    }
}

public interface ILend
{
    public void Lend(Individual i);
}

public class Jack : ILend //Same applies for Ben
{
    public void Lend(Individual i)
    {
        ...
    }
}

これは、あなたが指定した問題に取り組む方法です。

他のゴミ箱の例については、次のように実行できます。

public interface ITakeTrash
{
    public void TakeTrash(Trash t);
}

public Son : ITakeTrash
{
    public void TakeTrash(Trash t);
}

public class Mum  //Same applies for dad
{
    Son mySon = ...

    mySon.TakeTrash(t);
}

あなたのお母さんもお父さんもゴミの扱い方を知りませんが、あなたがゴミの処理方法を知っていることを知っており、それが彼らの関心事です (上記と同様に、あなたはベンとジャックがあなたに与えることができることだけを気にします)お金も他の当事者もあなたが返済できることだけを気にかけています

基本的に、異なることを行う同じ名前のメソッドで2つの異なるインターフェースを実装するとどうなるかを言って、あなたがどこに行こうとしているのか理解しています。そのようなシナリオに陥った場合、それは設計の悪さによるものだと思います。無数の異なることを行う単一のクラスを構築することはお勧めしません。これが理由の 1 つです。

一方で、同じ名前のメソッドで同様のことを行う 2 つのインターフェースがあるとしたらどうなるでしょうか。次に、答えは、インターフェイス同様のことを行い、同じ名前のメソッドがあるため、同じことをしている可能性が最も高いため、混乱する必要はないということだと思います。

この編集が問題の解明に役立つことを願っています。

于 2012-08-27T10:00:15.477 に答える
4

メソッドを適切に実装することは、お金を与えることとは異なります。ゴミ出しの様子です。ママとパパにゴミを出すと約束したら、一度ゴミを出してしまえばいいのです。

于 2012-08-27T09:57:05.083 に答える
1

例として、2 つのインターフェースがあり、どちらも同じ関数 PrintIt を持ち、クラス MyClass は両方のインターフェースを実装しています。

interface IAInterface
{
  void PrintIt(string s);
}

interface IBInterface
{
  void PrintIt(string s);
}

class MyClass : IAInterface, IBInterface
{
  public void PrintIt(string s)
  {
    Console.WriteLine(s);
  }  
}

を通じて複数のインターフェースを参照できます。

  1. クラス オブジェクト
  2. IAInterface インターフェースのリファレンス
  3. IBInterface インターフェイスのリファレンス

    MyClass _class = new MyClass();
    _class.PrintIt("Class"); 

    IAInterface _aInterface = (IAInterface)_class;
    _aInterface.PrintIt("IAInterface");

    IBInterface _bInterface = (IBInterface )_class;
    _bInterface.PrintIt("IBInterface");

明示的なインターフェース実装を提供することもできます...

class MyClass : IAInterface, IBInterface
{
  public void IAInterface.PrintIt(string s)
  {
    Console.WriteLine("AInterface - {0}", s);
  } 

  public void IBInterface.PrintIt(string s)
  {
    Console.WriteLine("BInterface - {0}", s);
  }   
}
于 2016-05-05T09:58:56.430 に答える
0

どちらのメソッドも同じ名前と同じシグネチャ (つまり、同じ戻り値の型と同じ引数の定義) を持っているため、両方のメソッドが同じであると見なされます。

于 2012-08-27T10:08:38.147 に答える
0

親クラスは子クラスによって消費されるように設計されていますが、インターフェイスは子クラスによって実装されるように設計されています。したがって、両方の親インターフェイスが同じメソッドを持っていても、それを継承しても子クラスに混乱は生じません。

参考:https ://dotnettutorials.net/lesson/multiple-inheritance-csharp/

于 2021-02-08T12:58:46.477 に答える
0

異なるインターフェイスから同じ名前のメソッドを実装する必要がある場合。これを試して。

interface IFoo
{
    void SayHello();
}
interface IBar : IFoo
{
    new void SayHello();
}
class myFooBarImp : IFoo, IBar
{
     void IFoo.SayHello()
    {
        Console.WriteLine("Hello from IFoo implementation");
    }

     void IBar.SayHello()
    {
        Console.WriteLine("Hello from IBar implementation");
    }

    public void SayHello()
    {
        Console.WriteLine("Hello from SayHello");
    }

}



 class Program1
{      
    public static void Main()
    {

        myFooBarImp obj = new myFooBarImp();
        obj.SayHello();
        (obj as IFoo).SayHello();
        (obj as IBar).SayHello();
        return;        

     }
}
于 2013-08-30T15:48:30.217 に答える
0

多重継承では、使用するとひし形問題が発生しますが、

public class A 
{
    public virtual  void aMethod(); 
}
 public class B
{      
 public virtual void aMethod();
}

public class aClass : A, B
 {      
public override void aMethod()  
    {       } 
}  

上記のコードでは、 aClass に対して、 vTable 内の同じ aMethod() に対して 2 つのvPtrが作成されます。したがって、あいまいさが発生します(ダイヤモンド確率)

しかし、インターフェイスを使用している場合、vTable の概念はありません。vTable は、基本クラスと派生クラスのシナリオ間で diff 実装を呼び出す際に役立つためです。この場合、インターフェイスには実装が含まれないため、vPtr、vTable がないため、ダイヤモンドの問題はありません。

于 2012-08-27T10:20:33.900 に答える