3

This is language agnostic in the sense that my question applies for any language that has the interface concept. (or swift protocols)

Consider this program in C#:

interface Inter1
{
    int Count();
}

interface Inter2
{
    int Count();

}

public class SomeClass : Inter1, Inter2
{
    public int Count()  // which one is it ?
    {
        return 0;
    }    
}

static void Main(string[] args)
{
    Inter1 c = new SomeClass();
    int i = c.Count();
}

Or in C++: https://godbolt.org/z/dFLpji

I'm having difficulties making sense of why this is tolerated, even though it appears that all possible symbol references are unambiguous, since the static type is going to specify which function we are talking about.

But isn't it dangerously close to name hiding ?

illustration of the problem I'm thinking about:

// in FileA.cs on day 0
interface DatabaseCleaner
{
    void Execute();
}

// in FileFarAway.cs day 140
interface FragmentationLogger
{
    void Execute();  // unfortunate naming collision not noticed
}

// in PostGreAgent.cs day 141
public class PostGreAgent : DatabaseCleaner, FragmentationLogger
{
    public void Execute()
    {   // I forgot about the method for database cleanup, or dismissed it mentally for later. first let's test this
        allocator.DumpFragmentationInfo();
    }

    private Allocator allocator;
}

// client.cs
AgentsManager agents;
void Main(string[] args)
{
    var pa = new PostGreAgent();
    agents.Add(pa);
    // ... later in a different location
    DatabaseCleaner cleaner = agents.FindBest();
    cleaner.Execute();  // uh oh
}
v.oddou
  • 6,476
  • 3
  • 32
  • 63
  • 1
    So you are looking for the reason why languages allow such cases ? – Spotted Jan 11 '19 at 10:45
  • 1
    Related: [Java Method name collision in interface implementation](https://stackoverflow.com/q/2598009/1371329) – jaco0646 Jan 14 '19 at 14:20
  • @jaco0646 thanks, yes your link is the same question for java specially. Now I wonder if the standard committee of java explicitly knew that they forced the same implementation for 2 colliding methods, and accepted that as a "meh", or "yes that's desired", or did they just not think about it at all. – v.oddou Jan 15 '19 at 06:49
  • @Spotted absolutely – v.oddou Jan 15 '19 at 06:49
  • 1
    Related: [Why does Java allow different interfaces with the same signature?](https://softwareengineering.stackexchange.com/q/177501/197340) – jaco0646 Jan 20 '19 at 19:59

1 Answers1

1

There is no ambiguity here.

Interfaces/protocols is just a list of requirements saying what an object implementing/conforming to it must be able to do. Inter1 and Inter2 both says that whoever implements it must be able to Count(). So if you can Count(), you can implement both interfaces. It is simple as that. There is no ambiguity here because there is only one implementation of Count. Inter1.Count and Inter2.Count are the same thing.

Note that in C#, you can implement interfaces explicitly, essentially providing a different implementation of Count for Inter1 and Inter2. The behaviour is that the non-explicit implementations will hide the explicit implementations so you can only access the explicit implementations with a compile time type of the interface.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • ok let's forget about C# specificity allowing qualification of the overload, which is a solution only for definition, but the callers are still going to be routed by static type. Other languages still have the issue, for example C++ disallows completely qualified identifiers in member declarations. So it's out of the question to disambiguate in `SomeClass`. I added an illustration of the issue to the question :) – v.oddou Jan 11 '19 at 08:52
  • @v.oddou so you are saying that compilers should be smarter to warn you about potential dangers? You could say that casting is potentially dangerous, yet compilers don’t complain. The main job of the compiler is not to spot dangerous code but to compile code. You should feel grateful for what it does warn you of. – Sweeper Jan 11 '19 at 11:06
  • I guess I was expecting an explicit care of that very case, in the wording of a language specification papers. In language specs, any piece of text is a concentration of deep thinking about all possible repercussions. So it's often possible to get a feel of the rationale, or even the original discussions like working group papers. My question is then "is this merely an unforeseen possibility emerging from interface feature ? otherwise said a flaw in the spec." or "is it a conscious and discussed decision to allow that, by standard committees". – v.oddou Jan 15 '19 at 06:31
  • I had a second thought about your comment, and noticed that you took it from the user point of view. "be grateful that compilers help you for some stuff". That's not my case. I am creating a compiler, so my question is "should I specify that this construct is forbidden in my language ?". So considering specifying a language is super hard, I want to get history of other languages in consideration prior to a decision. – v.oddou Jan 15 '19 at 06:45
  • @v.oddou Personally, I would not forbid that if I were writing my own language. I think spotting things like this should be the job of linters. The problem here is merely just having interfaces with methods that have the same name, which might happen not so rarely, and sometimes there is nothing wrong with that. Issuing a warning is the most I would do. – Sweeper Jan 15 '19 at 07:30