‘Stupid’ Question 11: Why isn't there multiple inheritance in C#?
[To celebrate my first year of programming I will ask a ‘stupid’ questions daily on my blog for a year, to make sure I learn at least 365 new things during my second year as a developer]
This is my mum and dad (2011). I’ve inherited a lot from both of them- as they have from their parents and so on. This multiple inheritance does make things more complicated than if single inheritance was possible.
So I was wondering why there isn’t multiple inheritance in C#,- to be honest I actually never questioned that before. With the whole Mammal inherits from Animal examples in books, it seemed logical. But I have two parents, and I’ve inherited from both of them. How come we don’t do this in C#?
You can give this one a long answer, or a short one. I’ll go for the short one here, because I am quite sure I’ll get some good comments on this one.
And by the way, I LOVE the comments, I read all of them,- and I still get super excited when I get an email that a new comment has been made. It makes my day, short or long- I am very very happy for the time and effort people put to add something very valuable to this site (and my life) – a conversation! Me like a lot!
So the answer: (short version of this one)
- Different implementations of MI across languages makes it a challenge to make a language-neutral implementation.
- Interfaces can be used instead, which makes MI a bit redundant.
- MI adds complexity in regards to casting, reflection and so on.
Plus a little quote from Stackoverflow: (funny description of the problem)
Multiple inheritance of implementation is what is not allowed.
The problem is that the compiler/runtime cannot figure out what to do if you have a Cowboy and an Artist class, both with implementations for the draw() method, and then you try to create a new CowboyArtist type. What happens when you call the draw() method? Is someone lying dead in the street, or do you have a lovely watercolor?
I believe it’s called the double diamond inheritance problem.
Leave a comment (via email)
Thank you Martin! I will :)
It is indeed the diamond problem and the issue is that the problem is so complex to solve that the effort to solve it does not meet the value it might give. I say might because no one have yet really proved that there is any great value in multiple inheritance except a few edge cases. So value does not match effort, that's the reason for not adding it into C# or the CLR. This is the explanation I got from the man himself Hejlsberg at one of the MVP-summits I attended.
I found your blog a couple days ago and I love what you are doing. I am also an aspiring developer, but my drive hasn't evolved as yours has yet. Your blog inspires me to ask more questions and become more curious about the subject, plus I learn a little bit more each day. I just started getting into ASP.NET MVC 3 about a month ago and it is becoming more challenging but interesting at the same time. Keep up the good work! Maybe ill be able to answer a question soon!
Isn't also the analogy with Mom + Dad -> Child a bit off? In all simplicity we inherit 50% from mom and 50% from dad, so in order for multiple inheritance in C# to work the same way that would mean we would have to define which half (third or fourth) we would get from the different classes. public class Me: Mom, Dad Would simply give me all traits and features from both my mom and dad. I think I'd end up looking and acting a bit strange :)
"Inheritance" in OOP world is not an inheritance in its common sense (that was unfortunate to use that word to describe that kind of relationships between classes). When we say "inherited" from something we suppose that child broke from their parents and now it's completely separate entity. In OOP a subclass continues to bear it's parent code inside it whole life, so to speak. Imagine that your hair are getting grey along with your dad. Now, imagine you allow those kind of effects from all your ancestor. And the ask yourself, what should happen if your dad's hair is becoming gray, but your mom's is not?
Yngve Bakken Nilsen : If one was to take the parents example literally- then I guess you would be right (not what I was going for)
I've found that one of the best sources for learning about C#, including topics such as multiple inheritance, is Eric Lippert's blog: http://blogs.msdn.com/b/ericlippert/ Plus his answers on StackOverflow can be very informative e.g. http://stackoverflow.com/questions/3270463/why-c-sharp-does-not-support-multiple-inheritance Hope this helps :)
That is not exactly the Diamond problem, but it's close. For the exact Diamond problem, consider our Artist & Cowboy classes. Each derives from a "Human" class, which mean that in every Cowboy and in every Artist, there is contained a Human. And when we create a CowboyArtist, it will contain both a cowboy and an artist, which means it contains two humans. Drawn as as inheritance chart (this is probably going to get managed): .....Hum ..../....\ ..Cow..Art ...\...../ ..CowArt It forms a diamond. The simple reason why those languages don't allow it, is that MI generally causes more problems than it solves (because it really doesn't solve that many problems)
Hi Iris, check this one : http://stackoverflow.com/questions/995255/why-is-multiple-inheritance-not-allowed-in-java-or-c and http://www.comp.lancs.ac.uk/~marash/SlidesCpp/slides/sld088.htm I think it will help you ... PS : Hope you better from your migraine :-)
Yep, the MI pro's are few and far between. The con's are apparent and looming, so most languages simply steer clear of such things. There are exceptions, but most have limitations on MI ideas - e.g. C++ enforces a concept of requiring the specification of which super-class is to be used when calling a multiple-inherited method/property. Other languages allow only multiple implementations. E.g. Java allows a single super-class, but multiple "interfaces". The difference here is that an interface is like a class skeleton / abstract class - i.e. only defining what methods a class should have, not implementing those in the interface itself. E.g. you could have something like an interface for OutdoorsPerson, which is inherited by Mountaineer & Kayaker. The OutdoorsPerson would define a method for FavouriteActivity but not implement it - leaving it up to the "child" class to implement. This then still allows poly-morphism to those methods/properties (which is probably the most notable pro for MI). The only language which I've found implements MI decently is Common Lisp's CLOS (Common Lisp Object System) - MOP (Meta Object Protocol) system. But that's probably more to do with Lisp itself - since the class is modifiable (including its inheritance) at every step from source / interpretation / compilation / runtime. E.g. even after instantiating a CowBoy object from the class at runtime, a change can be made to the CowBoy class to now inherit from OutDoorsPerson instead of Human - the MOP modifies the data in RAM to incorporate the new super-class's methods / properties (overwriting the implementation of the old same-named versions). So when now called something like FavouriteActivity, it is read from OutDoorsPerson instead of Human (which doesn't have such property). And the MOP allows you to revert back again by modifying the CowBoy class's inheritance back to what it was - thus not loosing any data in this process. So in effect Lisp allows single inheritance, but modifiable to allow "other" inheritance when needed.
Multiple inheritance solves a primary CS problem. It reduces the amount of code written. Why this is never recognized and understood to be more important than other reasoning, is really a failing of developer culture. We often trade mind-numbing complexity (Regex) or conceptual acrobatics (Perl) to reduce the time to develop and reduce bugs (increased code length is the only metric we can prove increases both), but this problem? No. Why? The fact that there's no uniform decision on how to determine method precedence is solved (use the format of interfaces). Many of the scripting languages (Ruby, Scala, PHP, etc) have had no problem implementing "traits/aspects" which are interfaces with implementation. It's obvious from my experience, that many developers are simply not familiar enough with large robust and well-written systems to understand when multiple inheritance is useful versus dangerous (in terms of complecting a problem). How many times have you encountered a system with hundreds of interfaces? How many times have you found yourself making compositional helpers that consume an interface and return a static method (effectively always returning the same implementation for the interface)? I've done it quite a bit. It's boilerplate and unnecessary. Let's see more multiple inheritance at the method level.
I find it very frustrating that I have to copy and paste interface implementations to a new class I have written. I don't see why with the CowboyArtist.Draw() problem that the compiler cannot simply say that .Draw is ambiguous and either force you to implement it anew or qualify it like CowboyArtist.Artist::Draw(). This is how c++ did it and it is fine. Now I have such ugly code.
Last modified on 2012-07-29