接口如何解决钻石问题

时间:2012-08-27 09:55:19

标签: c# oop diamond-problem

我需要和你讨论一件事。我一直在阅读有关接口的信息,它是类之间的契约接口,该类将提供接口的所有方法的实现。为了解决着名的钻石问题,我们有接口。 喜欢(我正在使用C#)

public interface IAInterface
{
     void aMethod();
}

public interface IBInterface
{
     void aMethod();
}

现在

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

     }
}    

通过上面的代码,据说aClass提供了接口方法的实现。我的困惑是:如果它是类和接口之间的契约,那么我们怎么能说与两个接口的契约都得到满足呢?

一个现实世界的例子, 就像我和杰克订的那样,我会同时给他5美元,我也和Ben签了合同我会给他5美元,现在给他们中的一个(杰克或本)提供5美元我怎么说我和他们两个都履行了合同?

我的问题似乎很幼稚,但这让我很困惑。

7 个答案:

答案 0 :(得分:9)

接口保证将实现一组给定的方法。该接口不关心如何实现代码。与扩展类相反,当您扩展类时,您正在使用一些预定义的代码。

如果使用相同的方法扩展两个类,比如methodA,并调用此方法,则编译器将不知道它需要运行哪个类。另一方面,当您使用相同的方法实现两个接口时,由于实现是在您自己的代码中编写的,因此编译器将知道在哪里找到实现。

所以基本上,当你实施某些东西时,你保证会提供一些服务。

编辑:我会尝试并以一些面向对象的方式转换它,希望能让事情更清晰。

杰克和本将保证他们会借给你钱,另一方面,你保证会还钱,因此,从OO的角度来看,你可以这样看:

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);
}

你的母亲和父亲都不知道如何处理垃圾,但是,他们知道知道如何处理它,这就是他们关心的事情(就像上面一样,你只关心Ben和Jack可以给你钱,而其他各方只关心你可以还钱,所涉及的真的 非常关心你是怎么做的。

我确实理解你要去的地方,基本上说如果我使用具有相同名称的方法实现两个不同的接口,那么会做什么。如果你最终遇到这种情况,我认为这可能是由于糟糕的设计。我不建议建立一个能完成各种不同事情的单一课程,这也是其中一个原因。

另一方面,您可能会问,如果我有2个接口使用相同名称的方法做类似的事情怎么办?然后,我认为答案是,因为接口类似的事情,并且你有相同名称的方法,所以很可能你做的是同样的事情,因此,你不需要让自己迷惑。

我希望这次编辑有助于解决这个问题。

答案 1 :(得分:4)

好的实施方法不像给钱。这就像取出垃圾一样。如果你答应妈妈和爸爸取出垃圾,就可以把垃圾拿掉一次。

答案 2 :(得分:1)

作为一个例子,我们有两个接口,它们都具有相同的功能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. class object
  2. IAInterface接口的参考
  3. IBInterface接口的参考
  4.     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);
      }   
    }
    

答案 3 :(得分:0)

由于两种方法具有相同的名称和相同的签名(意味着相同的返回值类型和相同的参数定义),因此假设两种方法都相同。

答案 4 :(得分: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()创建两个 vPtr 。因此出现歧义(钻石概率)

但是当你使用接口时,没有vTable的概念出现。因为vTable在基类和派生类场景之间用于调用它们之间的diff实现是有用的。在这种情况下,接口不会包含任何实现,因此没有vPtr,vTable,因此没有钻石问题。

答案 5 :(得分: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;        

     }
}

答案 6 :(得分:0)

父类设计为由子类使用,而接口设计为由子类实现。因此,即使两个父接口的方法相同,继承它也不会对子类造成混淆。

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