Click here to Skip to main content
15,884,298 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
Hi all,
I'm having a little problem designing an Interface I have (not the GUI).
What I basically have is two Interfaces that do the same, but one of them needs to get an extra parameter to a Function.
VB
Public Interface IDoSomething(Of T)
    Function DoSomething(ByVal something As T) As String
End Interface

Public Interface IDoSomethingSlightlyDifferently(Of T)
    Inherits IDoSomething(Of T)
    Function DoSomething(ByVal s As String, ByVal something As T) As String
End Interface
The above is not impossible, but the IDoSomethingSlightlyDifferently now has an overload for the DoSomething Function. One that will never be called...
The IDoSomething is to be used and implemented by the user and another Class uses IDoSomething as an input parameter.
IDoSomethingSlightlyDifferently is to be called from some Reflection code (which calls the overloaded function).

So while both Interfaces serve the same purpose the manner in which they are called is different. Does that mean one should not Inherit the other? Or should I Inherit them and simply have an empty Function that throws a <code>NotImplementedException?

Actually, as I wrote this I think I found my own answer. IDoSomething and IDoSomethingSlightlyDifferent are probably never interchangeable. You either Implement one and the other will never be called or you Implement both and you now have a Class that does two things (which look the same, but are still slightly different). So I guess the answer is they shouldn't Inherit.

I'm still curious and looking forward to some of your opinions on this matter. It's something that has been bugging me for a while.
Thanks.
Posted
Updated 17-May-12 20:25pm
v2
Comments
Maciej Los 18-May-12 7:22am    
Good question, my 5!
Sander Rossel 18-May-12 8:55am    
Thanks. I answer questions here too from time to time. I know how annoying a badly written question is ;)
Although I'd much rather have an answer :p
Sergey Alexandrovich Kryukov 19-May-12 22:20pm    
If you think so, my answer might seem interesting to you... :-)
--SA

1 solution

I see no problem here at all. The interfaces may inherit one from another or not. A class or a structure can implement either of the two or both of them. How exactly you build this hierarchy depends on the application of all those types and does not depend on signatures of the methods you show in your sample and — pat attention! — on the names of these two methods.

You do only one mistake here: you say "one… will never be called". This is not true. To understand it, for a minute, give your two methods you called DoSomething two distinctly different names. Will you see any problem in this case? My statement is: it makes no difference at all if you give the same name or two different names to these two method. No difference at all, in all cases.

Why? To understand it, it's enough to note that they have different number of parameters and no optional parameters (introduced in C# v.4). (This is sufficient but not necessary condition.) There are no situations where a compiler cannot determine a call to which of the function is implied. But even when there are cases where a call statement has some ambiguity, the use of the call to any of the methods of the same name (in one declaring type) is always possible.

To complete this, I want to give one general note. I understand the term "overloaded method", but try to never use it myself. This is one of the most misleading terms in the industry (another one is "race condition"; without actual knowledge on what is understood under this term it's nearly impossible to make a correct guess on what is it). "Overloaded method", coined by someone by a bad luck, does not really mean anything material. It's just so happened that in older programming language, their authors required that different functions had distinctly different names, just to make compilers simpler. Later on, people decided to give more convenience to the users of the language. There is nothing "overloaded" simply because nothing is "loaded" here.

The problem is that some idiotic activity is running around this trivial notion. The similarity between "override" and "overload" keeps this smelly fire burning. On CodeProject, I even saw the speculations about "compile-time polymorphism" associated with "overloading" as opposed to "run-time polymorphism" associated with overriding. There is nothing like any kind of polymorphism related to "overloadinig" by one simple reason: there is no such thing as "overloading" as a phenomenon. Two different methods with identical names but different signature behave in exact same was as if the were named differently. I tried hard to debunk this myth, but probably this is one pretty common myth, one of those passed through generations without any critical thinking applied to it.

—SA
 
Share this answer
 
Comments
Shahin Khorshidnia 20-May-12 2:42am    
Perfect as always (+5)
Sergey Alexandrovich Kryukov 20-May-12 19:22pm    
Thank you, Shahin.
--SA
Sander Rossel 20-May-12 5:46am    
Thanks for your, once again, detailed answer. The problem, however, is not really naming the methods the same (I think you misunderstood my question, for which I apologize if I wasn't clear enough). The problem is that one is not interchangeable for the other even though they do the same. Which sounds pretty weird to me. So when you say 'it makes no difference at all' you only mean giving the functions the same name. But Inheriting from a type that represents the same logical object, but are technically not interchangeable DOES make a difference I think.
See it like this. I have two Interfaces. Both Interfaces define a house. However, one defines a house where we ONLY enter through the door while the other represents a house where we ONLY enter through the window. We can define a function like 'EnterTheHouse' and in one case this function gets a Door as parameter while in the other case it gets a Window as parameter. The problem is that there are no houses where we can enter by Door and Window. So if the IEnterHouseByDoor Inherits IEnterHouseByWindow you will always have two functions defined for entering while one of the two is impossible to call (should throw an InvalidOperationException). So, why then, would IEnterHouseByDoor Inherit IEnterHouseByWindow? While both Interfaces represent a house that can be entered they have a (seemingly just slightly) difference which makes them completely different types.
In my case the IDoSomethingSlightlyDifferently is called through Reflection, which really only calls DoSomething(String, T) and never DoSomething(T). IDoSomething is called by another Class which will always call DoSomething(T), but never DoSomething(String, T). This is because the String parameter is gotten through Reflection.
So once again, they do the same, but because of the way they are called they are never interchangeable...
Your discussion against the term 'overloading' is very interesting and I will remember it. Though I don't really think it's relevant for my question :)
I hope my question is clear to you now.
Sergey Alexandrovich Kryukov 28-May-12 17:20pm    
Well, I discussed the situation with "overload" just because this is the way how you formulated it, no matter if you actually have problems with it or not. In this sense, this discussion is relevant. Then everything is reduced to how exactly do you call an interface method through Reflection. Your "never called" is still not explained. I personally don't see why either of method can not be called -- you can actually do it. Now, there is not a problem from the poor technology, but it can be a problem with reasonable design of the code, as nearly everywhere in OOP. You cannot consider interface as a poor access tool. It is always an abstraction device which you can use either for interface-level polymorphism, which is very different from "classical" polymorphism, or as a set of the different views at the same object (of course I mean the case where you implement both interfaces by one class, otherwise there is nothing to talk about). These two aspects are somewhat related, because interface-level polymorphism allows the same object to participate in two or more different polymorphic sets -- do you see the similarity. So, keeping this purpose in mind, you can have different places in code, one is "interested" in some house from the standpoint of the IDoSomething, another one -- IDoSomethingSlightlyDifferently; and for each case you can obtain desired interface and ignore another one, and hence use just one of those methods. If you don't need that, the whole discussion would not make sense, but if you do, you look at it this way.

And, by the way, a good way of using Reflection is getting the type by its interface, not by name of the class, not by the name of any method. This is the way to avoid dependency on some string constants, which is a bad thing because a compiler cannot perform the check of correctness of such code -- misspell a value of a string, and the compiler won't detect it.

--SA
Sander Rossel 28-May-12 17:29pm    
Yes, I see what you mean. By "never called" I actually meant "not called by the library I am making", but that doesn't mean that it could or would never be called by other code. In my case I could be calling it, but probably won't and maybe not want. I'd have to think that part over I guess.
Of course I am using Reflection by getting the type of the Interface. Never strings. And certainly not the name of a Method (those tend to change).
Thanks for your, once again, detailed answer. It helps me greatly :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900