Pregunta

I need to discuss one thing with you. I have been reading about the interface that it is a contract between the class the interface that the class will provide implementation of all the methods of the interface. To solve the famous diamond problem, we have interfaces. Like (I am using C#)

public interface IAInterface
{
     void aMethod();
}

public interface IBInterface
{
     void aMethod();
}

Now

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

     }
}    

By above code, it is said that aClass has provided the implementation of both the methods of the interfaces. My confusion is: If it is a contract between the class and the interface then how can we say that contract with both the interfaces is fulfilled?

A real world example, Like I have contract with Jack that I will give him 5 dollars at the same time I also have contract with Ben that I will give him 5 dollars, now by providing 5 dollars to one of them (either Jack or Ben) how can I say I have fulfilled the contract with both of them?

My question may seem childish but that is confusing me a lot.

¿Fue útil?

Solución

Interfaces guarantee that a given set of methods will be implemented. The interface does not concern itself on how will the code be implemented. As opposed to extending classes, when you extend a class you are using some predefined code.

If you extend two classes with the same method, say, methodA, and call this method, then, the compiler will not know which one will it need to run. On the other hand, when you implement two interfaces with the same method, since the implementation is written within your own code, the compiler will know where it needs to go to find the implementation.

So basically, when you implement something you are guaranteeing you will be offering some service.

EDIT: I'll try and take your example and turn it in some Object Oriented way, this will hopefully, make things clearer.

Jack and Ben will guarantee that they will lend you the money, you, on the other hand, guarantee that will pay it back, so, from an OO point of view you can see it like this:

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)
    {
        ...
    }
}

This is how I would go about the problem you have specified.

As for the other trash example, this is how you can go about it:

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

Both your mother and father do not know what to do with the trash, but, they know that you know how to deal with it, and that is what they care about (just like above, you only care that Ben and Jack can give you money and the other parties just care that you can pay it back, none of the involved really care how you do it.

I do understand where you are trying to go, basically saying what if I implement two different interfaces with methods having the same name that do different things. If you ever end up in such a scenario, I think that that would be due to bad design. I would not recommend building a single class which does a myriad of different things, this being one of the reasons.

On the other hand, you might ask, what if I have 2 interfaces that do similar things with methods having the same name? Then, I think that the answer would be that since the interfaces do similar things and you have methods with the same name then, it is most likely that you are doing the same thing, hence, you need not confuse yourself.

I hope this edit helped shed some light on the issue.

Otros consejos

Well implementing methods is not like giving money. It's like taking out the trash. If you promise mom and dad to take out the trash, it is enough to take out the trash once.

As an example we have two interfaces and both have same function PrintIt and class MyClass implements both interfaces.

interface IAInterface
{
  void PrintIt(string s);
}

interface IBInterface
{
  void PrintIt(string s);
}

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

You can refer to multiple interfaces through

  1. class object
  2. reference of IAInterface interface
  3. reference of IBInterface interface

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

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

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

You can also provide explicit Interface Implementation ...

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

Since both methods have the same name and the same signature (meaning same return value type and same argument definition), it is assumed that both methods are the same.

In multiple inheritance, the diamond problem will occur when you use,

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

Now

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

In the above code, for aClass two vPtr will be created for the same aMethod() in the vTable. Hence the ambiguity occurs (diamond prob)

But when you are using interfaces, no concept of vTable comes. Because vTable is useful between base and derived class scenario's in calling diff implementations among them. In this case, the interface doesn't gonna contain any implementation and so no vPtr, vTable and hence no diamond problem.

If you have to implement same named Methods from different Interfaces. Try this.

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;        

     }
}

Parent classes are designed to be consumed by the child class while the Interface is designed to be implemented by the child class. Therefore even though both parent interface has the same method, while inheriting it won't create a confusion to the child class.

Reference : https://dotnettutorials.net/lesson/multiple-inheritance-csharp/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top