All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer.
Occasionally I get questions on why does .NET not support multiple inheritance. It is actually a pretty interesting question to contemplate with, though I usually start the conversation by asking: "what issue requires multiple inheritance to solve?".
More often than not, the question surfaces when people are trying to "do the right thing" by correctly refactoring code in an object-oriented manner, and facilitate code reuse by using inheritance, but encounter challenges when trying to reuse methods and code behaviors defined in separate places of the class hierarchy. Thus the most "natural" question was, if I can just inherit the code from these classes...
Many decisions in language design, just like software projects, are balancing acts between various trade-offs. There are many very interesting conversations happening in the community, such as the debate on generics and closures on the Java side (for example: How Does Language Impact Framework Design? and Will Closures Make Java Less Verbose? and James Gosling's Closures). Interesting to see how much thought goes into each seemingly small decision on adding specific language features, or not adding them.
There were many factors that influenced the .NET team to favor not implementing multiple inheritance. A few of the more prominent ones include:
Now Java doesn't support multiple inheritance as well, though probably for a different set of reasons. Thus it is not a case of simple oversight in design or lack of maturity, as it was a careful and deliberate decision to not support multiple inheritance in the .NET and Java platforms.
So what's the solution? Often people are directed to using interfaces, but interfaces don’t lend themselves very well to meet the requirements of reusing code and implementing separation of concern; as interfaces are really intended to support polymorphism and loosely-coupled/contractual design. But other than trying to tie behaviors into object inheritance hierarchies, there are many alternative approaches that can be evaluated to meet those requirements. For example, adopting relevant design patterns like Visitor, frameworks like MVC, delegates, mixins (interfaces combined with AOP), etc.
Bottom line is, there are considerably elegant alternatives to inheriting/deriving behavior in class hierarchies, when trying to facilitate code reuse with proper re-factoring. Plus trade-offs in code reuse vs. the costs incurred to manage the reuse is another full topic in itself. In some cases it may have been simpler to have multiple inheritance and access to sealed classes, but the trade-offs may have been greater costs in other areas.
PingBack from http://microsoftnews.askpcdoc.com/?p=3133
Ancora su .NET e l'ereditariet
> Often people are directed to using interfaces, but interfaces don’t lend themselves very well to meet the requirements of reusing code and implementing separation of concern; as interfaces are really intended to support polymorphism and loosely-coupled/contractual design.
I disagree. Using interfaces in conjunction with wrapping can cover 9% out of the remaining 10% that isn't covered by interfaces alone. You can even do "virtual base classes" that way, though rather more explicitly than in C++. The only real problem, aside from the perfomance penalties, is the tediousness of writing all the wrapping/delegating code; but add syntactic sugar to do that (delegate calls to methods of a particular implemented interface to a wrapped object) with a single line of code, and I won't miss my beautiful C++ diamond-shaped class graphs anymore.
int19h: Thanks for the feedback! I apologize for not clarifying, as that was exactly what I had in mind as well. In my opinion interfaces are perfect candidates for doing what you described, but just like you mentioned, it requires additional thought and the wrapping/delegating code. It works, but just not as elegant as multiple inheritance would've provided (comments I've received from other developers). My intention was to point people away from trying to reuse code just by inheritance, but look for alternatives in design patterns and other means (which more often than not will require the use of interfaces anyway). Point being - look beyond inheritance or trying to use interfaces to do what multiple inheritance does, if the purpose was to reuse code in a well-refactored manner; as sometimes the most effective path to an issue may not be a straight line.