Why is it important which interface method is called?

I am studing interfaces, and at a point I came to explicit interfaces implementation. In a tutorial video at about 2:55 it says that when a class inherits 2 different interfaces, and if those two interfaces has a method with the same name, there is an ambiguity on which interface's method will be called.

using System;

interface I1
{
    void InterfaceMethod();
}

interface I2
{
    void InterfaceMethod();
}

public class Program : I1, I2
{
    public void InterfaceMethod()
    {
        Console.WriteLine("I1 Interface Method");
    }

    public static void Main()
    {
        Program p = new Program();
        p.InterfaceMethod();
    }
}

I am confused because, interfaces doesn't have method definitions, so why does it matter which interface's method is called? Both methods are identical with the same name.

3 answers

  • answered 2018-01-11 21:33 JamesFaix

    It looks like you're using C#. The language involved is very important for this question. I would recommending adding a tag for that when asking a question like this.

    I believe the reason C# treats this as an ambiguous reference, rather than just using the same implementation for both, is that

    1. If you must declare both methods in your implementing class, then the two methods with the same name can have different return types, so the same system can be used in a wider range of problems.

    ```

    interface I1 { 
        int Foo();
    }
    
    interface I2 {
        string Foo();
    }
    
    class C : I1, I2 {
        int I1.Foo() { ... }
    
        string I2.Foo() { ... }
    }
    
    1. If one interface is updated to change a parameter for example, code using that interface will be easier to update, without breaking other interface implementations.

  • answered 2018-01-12 16:38 Mike

    It is important which is called because, although the interface methods might have the same name (and parameters and even return type), they might have completely different meanings in the context of those different interfaces. Therefore you have to be able to specify which implementation method to use for each interface.

    For example:

    interface IVehicle
    {
        int GetNumberOfWheels();
        int GetNumberOfDoors();
    }
    
    interface ICheeseContainer
    {
        int GetNumberOfWheels();
        int GetNumberOfWedges();
    }
    
    class CheeseDeliveryTruck : IVehicle, ICheeseContainer
    {
        // Object has to be able to return the number of wheels on the truck
        // when used as an IVehicle.
    
        // Object has to be able to return the number of cheeses in the back of
        // the truck which are packaged as wheels when used as an ICheeseContainer.
    }
    

  • answered 2018-01-12 17:02 Jon Hanna

    Why does it matter which interface's method is called? Both methods are identical with the same name.

    And maybe that's okay. But maybe it's not.

    In this case the result of the method is to output "I1 Interface Method", indicating that in real code the equivalent does care that it's I1.

    When we create methods we give them names that try to be short and clear in meaning based on the meaning a word or few words have in a natural language like English. This can result in there in fact being different (whether very different or subtly so) purposes to two methods with the same name. We would then want to have separate implementations.

    It's nice when things line up so that we can indeed use the same method for both, but it's also great that we're not trapped by that when inappropriate.

    We'd also have to have separate implementations for interfaces with methods with the same name and parameter signature but different return types, since C# can't distinguish between these. A common example is IEnumerable<T> since it has a GetEnumerator() method that returns IEnumerator<T> but inherits from IEnumerable which has a GetEnumerator() method that returns IEnumerator. (IEnumerator<T> and IEnumerator are also examples of this same principle).

    Another case where we might want to do explicit interface implementation is when a member isn't very useful in the context of the concrete type. For example List<T> implements ICollection<T>. That interface has an IsReadOnly property that is pointless in the context of working with List<T> directly as we know it's false because List<T>s are inherently not read-only. It is important when we're working on an ICollection<T> reference though (and of course, the rules require it be implemented one way or another), so it's done as an explicit implementation. ReadOnlyCollection<T> not only does the same thing (but of course, returning true instead of false) but also makes methods like Add() which are clearly pointless given that they will always throw an exception no matter what, explicit.