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

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

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

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

编辑:我将尝试以您的示例为例,并以某种面向对象的方式对其进行转换,这有望使事情变得更清楚。

Jack 和 Ben 会保证他们会借给你钱,而另一方面,你保证会偿还,所以,从 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);
}

你爸妈都不知道怎么处理垃圾,但是,他们知道知道怎么处理,这才是他们关心的(就像上面一样,你只关心本和杰克能给你钱和其他方只关心你能不能还钱,没有人真正关心你是怎么做的。

我确实了解您想要去哪里,基本上是说如果我使用具有相同名称的方法实现两个不同的接口来做不同的事情。如果您最终陷入这种情况,我认为那是由于设计不当造成的。我不建议建立一个做无数不同事情的单一类,这是原因之一。

另一方面,你可能会问,如果我有 2 个接口用同名的方法做类似的事情怎么办?然后,我认为答案是,由于接口类似的事情并且你有同名的方法,很可能你正在做同样的事情,因此,你不必混淆自己。

我希望这个编辑有助于阐明这个问题。

于 2012-08-27T10:00:15.477 回答
4

好的实施方法不像给钱。就像倒垃圾一样。如果你答应爸爸妈妈倒垃圾,倒垃圾一次就够了。

于 2012-08-27T09:57:05.083 回答
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. 类对象
  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

在多重继承中,使用时会出现菱形问题,

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 在基类和派生类场景之间在调用它们之间的差异实现时很有用。在这种情况下,接口不包含任何实现,因此没有 vPtr、vTable,因此没有菱形问题。

于 2012-08-27T10:20:33.900 回答
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

父类被设计为由子类使用,而接口被设计为由子类实现。因此,即使两个父接口具有相同的方法,在继承它时也不会给子类造成混乱。

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

于 2021-02-08T12:58:46.477 回答