Doubt: How does Java and C# .NET compensate for not having multiple inheritance?
Posted by iamtheaashish@reddit | learnprogramming | View on Reddit | 20 comments
I have been reading a book named "The object oriented thought process". There is a topic of multiple inheritance in this book and its says that multiple inheritance is only supported by language like C++ and Java and C sharp does not support multiple inheritance because the disadvantages of having multiple inheritance ways more than advantages of having it.
My doubt is that how does Java and C sharp.net compensate for not having multiple inheritance. There is a paragraph given over here but I am not able to comprehend it.
"The modern concept of inheritance is that you can only inherit attributes from a single parent (single inheritance). Even though you can use multiple interfaces or protocol this is not truly multiple inheritance."
What is multiple interfaces exactly?
I would be greatful if you explain it to me please.
I have familiarity with C++ and learning C# right now.
vowelqueue@reddit
Inheriting from a class means you inherit both its state (i.e. fields declared in the parent class) and its behavior (i.e. non-private methods).
An interface is just a collection of methods, and implementing an interface means you inherit and/or have to define all of that behavior.
So essentially the primary difference between true multiple inheritance and implementing multiple interfaces is that the child class can’t inherit state from multiple direct parents.
The way to compensate for not having multiple inheritance, which is also a way to avoid using inheritance altogether, is to use composition.
Say you have state and behavior that you want to re-use, and that is contained within some class. Instead of inheriting from that class, you add a field to your class that contains an instance of the re-usable class and call into it.
iamtheaashish@reddit (OP)
Understood, thank you very much.
One more doubt along these lines.. "Say you have state and behavior that you want to re-use, and that is contained within some class. Instead of inheriting from that class, you add a field to your class that contains an instance of the re-usable class and call into it."
So you are talking about calling public member functions of the re-usable class?
Logical_Angle2935@reddit
Suppose you have a View base class. Each view needs a widget to draw on. So we see 'virtual Widget widget() = 0" in the View definition.
The derived GraphicsView class inherits View and implements widget() to return a GraphicsWidget instance which it owns. This is composition, GraphicsView is composed of itself and a specialized Widget-derived class.
In C++, GraphicsView could inherit both View and Widget as base classes and return pointer to self in the virtual widget() method. If one or both base classes are interfaces then you could also do this in other languages.
IMO this type of multiple inheritance is not a problem and often convenient. In my 30 years experience, multiple inheritance was a problem exactly once.
Both composition and multiple inheritance are tools in the toolbox to be used appropriately.
dkarlovi@reddit
Even in languages which support single inheritance you don't really want to use it, you should prefer interfaces and traits.
iamtheaashish@reddit (OP)
Umm what's the issue ? I know that multiple inheritance clutters the codebase and makes it difficult to understand. But why to avoid single inheritance also?
dkarlovi@reddit
Inheritance leads to very heavy object graphs where you can have several (say, 6-7) levels of parent-child relationships, it becomes super difficult to understand what's coming from where. It also leads to very leaky abstractions because for a thing to be available in a child, you make it available in the ancestor, but if it's not a direct parent, all the objects in between see it too.
A much better approach is so called composition: you don't inherit from a class, whatever the class does, you inject as your own dependency via an interface.
Let's take a common example: adapters. Let's say you have an system which reads file metadata and you want to support local files and S3.
With inheritance, you'd have: 1.
AbstractFileMetadataReaderwithabstract readFileMetadata2.LocalFileMetadataReader extends AbstractFileMetadataReader3.S3FileMetadataReader extends AbstractFileMetadataReaderYou use it like so
With composition, you'd have: 1.
FileMetadataReader(FileMetadataReaderInterface reader)2.FileMetadataReaderInterfacewithreadFileMetadata3.LocalFileMetadataReader implements FileMetadataReaderInterface4.S3FileMetadataReader implements FileMetadataReaderInterfaceYou use it like so:
reader = new FileMetadataReader(new S3FileMetadataReader)At first, this seems like it's more complex ("there's one more thing!"), until you see the code:
FileMetadataReaderdoesn't know or care which concrete reader it's using, it doesn't care, it's just a concrete class doing some workThe differences become apparent when you start adding features: 1. for the local file system, you might just need the file path 2. for the S3 file system, you might need the actual SDK injected for it to work
With the composition approach, you don't need to pretend these are the same thing, they're not, they just have a common feature, which the interface represents.
Dealiner@reddit
That's mostly just a trend that has become popular lately - OOP is bad, you should avoid inheritance and prefer composition. The truth is both have their uses.
WystanH@reddit
The real question is what does multiple inheritance buy your versus what does it cost you. For a long time now programmers have generally believed it doesn't offer enough for the trouble it causes.
It's a rather antiquated OOP paradigm, honestly... Ah, you do know your book is over a quarter century old?
Google "composition over inheritance" and "programming to an interface" to get an idea of were things are kind of at now. Also, google "multiple inheritance" and "avoid multiple inheritance" to see what the issues are.
iamtheaashish@reddit (OP)
Got you, I am a beginner and it's nice to learn and have discussions around such topics.
I will have to read more about composition and interfaces.
Thank you so much.
buzzon@reddit
You can always emulate multiple inheritance via composition, which is what multiple inheritance does on compiler level anyway.
iamtheaashish@reddit (OP)
Understood.
jipgg@reddit
C++ doesn't make the distinction between base classes and interfaces. In C++ an interface is in essence simply a base class with all its methods being abstract (virtual void do_something() = 0). C# and java make the explicit distinction between interfaces and base classes, and they provide a dedicated 'interface' keyword to define interfaces, which are roughly comparable to abstract base classes with the distinction that you can implement (inherit) multiple at the same time with slightly different syntax. That's in essence their way of providing multiple inheritance in a sense.
Jonny0Than@reddit
I would say that in C++, it’s more important that the interface has no data members rather than being abstract.
One of the biggest downsides of multiple inheritance is the diamond problem. Suppose you have a class B that has a data member
B::b. Then you have classes D1 and D2 that each inherit from B. So far so good. Now make class C that inherits from both D1 and D2. What isC::b? It’s actually ambiguous, because it could be referring toD1::borD2::b. It’s a nightmare.Any time multiple inheritance is involved, it’s usually best to follow the C#/Java restrictions of one base class, multiple interfaces. And the thing that makes something an interface is the lack of data members.
iamtheaashish@reddit (OP)
Got it, understood, thanks, conceptually it often results into kind of a race-condition.
iamtheaashish@reddit (OP)
Understood. I have a few simple doubts, I am sure they will get cleared once I see how exactly it's implemented. Thank you so much.
Conscious-Pace7669@reddit
Karyo_Ten@reddit
In general multi-inheritance is very seldom used. I think the ladt advocate of it is Julia since Nim deprecated them: https://github.com/nim-lang/RFCs/issues/65
iamtheaashish@reddit (OP)
Got you.
amazing_rando@reddit
An interface is basically just a list of methods you need to implement. So even though you can only have one parent object, you can qualify for as many interfaces as you want.
iamtheaashish@reddit (OP)
Got it thanks 🙏