-
[RESOLVED] Diamond Inheritance Problem - C#
This question is specific to C# not providing multiple inheritance unlike C++ and the need to go about using interfaces to implement multiple inheritance.
It’s about Multiple Inheritance and how to solve diamond Inheritance problem.
To begin with this is what my class design looks like, on a very high level.
struct DOB{
int dd,mm,yy;
}
class Player{
string firstName,lastName;
DOB dob;
string debutPlace, homeTown;
//a few methods and constructors also go into this class design
}
class Batsman : Player{
int runsScored, fiftyScored,hundredScored;
float battingAverage;
// a few methods and constructors are also part of this class
}
class Bowler : Player{
int oversBowled,wicketsTaken, runsGiven;
float bowlingAverage;
//a few methods and constructors are also part of this class
}
Now I want to create a new class called AllRounder. Going by the real-time characteristics of this object, an AllRounder in cricket is someone who is both a batsman and a bowler. As such I would have to create the AllRounder Class which has both Batsman and Bowler as its base classes.
Here is where I am starting to face the problem.
I understand that C# does not support multiple inheritance, but then again Multiple Inheritance can be achieved using Interfaces. Now every book stops with just this and gives a simple example on the same, but I haven’t found a proper suggestion/solution to this problem of mine (I am told that the problem I am referring to, is named as Diamond Inheritance Problem)
Until I was playing around with C++, this wasn’t a problem at all for me, since C++ supports multiple inheritance and also because Diamond Inheritance problem was solved by C++ by the help of virtual inheritance, which helped me inherit just one copy of the Player class on to my AllRounder class (without having to worry about me getting a copy of the Player class attributes through both the Batsman class and the Bowler class which are to be the base classes of AllRounder class as per my class design)
All people to whom I have approached with this problem, said Interfaces is my solution. But I understand that interfaces can only contain method signatures and cannot contain any data members. Java is a little bit different on this, the interfaces in the world of java lets you have data members also, but there also comes a limitation, the data members can only be constants.
My entire class design is trying to map the real time entities and the way they are visualized into classes, but because of the fact that multiple inheritance is not supported, I am not able to proceed further.
Can someone please help me with this query ?
-
Re: Diamond Inheritance Problem - C#
Interfaces are just templates of what a part of a class should look like. It specifies the methods that can be seen by the outside world, it doesn't actually implement any code.
So you have 2 interfaces IBowler and IBatsman. Then you create you 4 objects.
Code:
class Player { ... }
class Bowler : Player, IBowler { ... }
class Batsman : Player, IBatsman { ... }
class AllRounder : Player, IBowler, IBatsman { ... }
Inheriting from Player does actually give you data members and methods. Inheriting from the interfaces simply say that these specified methods exists. You will have to implement them each time for each object. Now when you are iterating over player objects, you can test to see if the player is an IBowler or IBatsman "object" AllRounder would be applicable to both.
-
Re: Diamond Inheritance Problem - C#
Hi
Thanks for the prompt reply.
But the problem is since the interfaces (As highlighted by you) IBowler and IBatsman arent allowed to include any data members, how would I go about defining the specific attributes of a bowler class and a batsman class is what I am not very clear about.
Would it mean that I would have to revamp my class design and include all the attributes of a batsman and a bowler again in the class "AllRounder" ?
Wouldnt this be a redundancy of attributes while defining AllRounder class, because an allrounder class basically should include all attributes that a Player, Batsman and a Bowler possesses and also if needed add its own AllRounder specific attributes.
But if I were to declare something like this
class AllRounder : Player, IBowler, IBatsman { ... }
then I would essentially have to re-declare all the Bowler and Batsman attributes in the AllRounder class ?
Kindly clarify. Hope am not going round in circles seeking a clarification here.
-
Re: Diamond Inheritance Problem - C#
I have understood your problem and I really liked the question you asked. I think you can not achieve what you want to using C#, with inheritance. But you can simulate a bit of similar behavior using composition. Your Allrounder class can contain and instance of Bowler and an instance of Batsman.
and by the way, where are the umpires and wicketkeeper :-)
-
Re: Diamond Inheritance Problem - C#
You declare PROPERTIES.
btw: Fields should ALWAYS be private.
-
Re: Diamond Inheritance Problem - C#
Nabeel
Thanks for the response. Yes I also had composition as a work around, but wanted to find out if C# does in fact have the same way of doing it, just as C++ lets me do. btw, since I got stuck at the AllRounder class itself, I gave up going further with the Umpire class and the fielders classes... :)
TheCPUWizard
Thanks for your response. Can you please elaborate your response with respect to Properties ? Would be referring to including properties in the interfaces (IBowler and IBatsman) or would be referring to including properties in the AllRounder class. I do understand that interfaces does let me include properties, which can be implemented by the class that inherits the interface, but then again I would be back to square one, of a redundancy of attribute definition in the AllRounder class with respect to incorporating the Batsman attributes and Bowler attributes. Kindly clarify.
-
Re: Diamond Inheritance Problem - C#
There is NO redundancy
Code:
interface I1
{
int Data { get; set; }
}
interface I2
{
int Data { get; set; }
}
class C : I1, I2
{
public int Data
{
get {.....}
set {.....}
}
}
-
Re: Diamond Inheritance Problem - C#
TheCPUWizard
Hi, I guess you missed out a portion of my question here.
The redundancy that I am referring to in the piece of code provided by you, is with respect to class C
I have a class called "Vehicle". I have derived two classes out of "Vehicle" viz., "Aeroplane" and "Ship". Now I am looking to create a new class called "Hovercraft", by deriving from both "Aeroplane" and "Ship" classes, because I have visualised that an object of type "Hovercraft" would essentially have the features of both "Ship" and "Aeroplane". Now this is what C# doesnt let me do.
Going by your explanation, I can go around creating interfaces for "Ship" and "Aeroplane" and have the class "Hovercraft" implement both these interfaces. But what happens to the data members of "Ship" class and "Aeroplane" class, which I am looking to inherit in "Hovercraft" class. Even though i define properties in the interfaces for "Ship" class and "Aeroplane" class, I still would have to define all the attributes of a "Ship" and an "Aeroplane" while I am creating a "Hovercraft".
I wanted to know if we had a way of getting this done just as in C++ wherein I can do a virtual inheritance and create "Hovercraft" from "Ship" and "Aeroplane" (Since both these base classes have a common base class "Vehicle" a virtual inheritance would be needed to do away with getting two copies of "Vehicle" attributes). I guess to do away with this is why C# got rid of Multiple Inheritance.
Kindly let me know if there is a way out of this ?
-
Re: Diamond Inheritance Problem - C#
Simple YOU DONT. .NET supports only single inheritance, and you need to consider this from well before you write your code.
Using the sample classes you described, I would create specific classes for each function (NOT parth of the Vehicle hierarchy) [Start, Stop, CheckFuel]. Then you combine them in the leaf classes "Ship", "Plane" and "Hovercraft" to provide the comprehensive view of that type of vehicle.
-
Re: Diamond Inheritance Problem - C#
TheCPUWizard
Thanks again for your response. I guess you mean to say that my class design(the example that I had initially mentioned when I started this thread) needs to be re-looked at and re-organized.
Am I correct ?
-
Re: Diamond Inheritance Problem - C#
That is EXACTLY what I am saying. :wave: :wave:
-
Re: Diamond Inheritance Problem - C#
Quote:
Originally Posted by hakuna_matata
TheCPUWizard
Hi, I guess you missed out a portion of my question here.
The redundancy that I am referring to in the piece of code provided by you, is with respect to class C
I have a class called "Vehicle". I have derived two classes out of "Vehicle" viz., "Aeroplane" and "Ship". Now I am looking to create a new class called "Hovercraft", by deriving from both "Aeroplane" and "Ship" classes, because I have visualised that an object of type "Hovercraft" would essentially have the features of both "Ship" and "Aeroplane". Now this is what C# doesnt let me do.
Hovercraft are both Aeroplanes and Ships? Well that's an interesting, if flawed assertion.
I think however your basic approach to the English grammar is flawed. In java, we have the very sensible notion that interfaces represent abilities (actions, verbs) not objects (nouns, stuff)
Aeroplane: IFlyable
Ship: ISailable
Hovercraft: IFlyable, ISailable
A hovercraft is not an Aeroplane and it is not a Ship. It is, strictly speaking more of a helicopter than anything else.. It does not plane on the air or the water, but relies on forced air to reduce friction with the resting surface. No matter, here we are talking about interfaces representing abilities, not objects
Quote:
Going by your explanation, I can go around creating interfaces for "Ship" and "Aeroplane" and have the class "Hovercraft" implement both these interfaces. But what happens to the data members of "Ship" class and "Aeroplane" class, which I am looking to inherit in "Hovercraft" class. Even though i define properties in the interfaces for "Ship" class and "Aeroplane" class, I still would have to define all the attributes of a "Ship" and an "Aeroplane" while I am creating a "Hovercraft".
True, because a hovercraft is not aship and it is not an aeroplane, so why should it inherit?
Quote:
I wanted to know if we had a way of getting this done just as in C++
Yes. Use C++ if you think it will make your program better
Quote:
Kindly let me know if there is a way out of this ?
Get typing code, not posts
-
Re: Diamond Inheritance Problem - C#
Quote:
Originally Posted by cjard
I think however your basic approach to the English grammar is flawed. In java, we have the very sensible notion that interfaces represent abilities (actions, verbs) not objects (nouns, stuff)
Aeroplane: IFlyable
Ship: ISailable
Hovercraft: IFlyable, ISailable
It is more the naming of the interface (...able) that indicates ability/action/verb. And this is a good thing.
The difference between an interface and a class REALLY is that the former has absolutely NO implementation details, while the latter has some or all of the implementation details.
The first example I can think are the collections:
IList/List, IDictionary/Dictionart, etc...
The differentiation between "static/state" and "action/operation" is at a more granular level:
Method = Ability/Action/Verb
Property = Adjective
-
Re: Diamond Inheritance Problem - C#
Quote:
Originally Posted by cjard
A hovercraft is not an Aeroplane and it is not a Ship. It is, strictly speaking more of a helicopter than anything else.. It does not plane on the air or the water, but relies on forced air to reduce friction with the resting surface.
Thanks for your elaborate explanation. I guess I got you too involved in my example and made you miss the idea behind my question which was originally "How to achieve multiple inheritance using Interfaces for a specific class design I had in mind"
Quote:
Originally Posted by cjard
Hovercraft are both Aeroplanes and Ships? Well that's an interesting, if flawed assertion.
If you could kindly go back to my first posting, you might notice that the class hierarchy that I had in mind, it replicates the exact real entity objects in the sport of cricket.
Quote:
Originally Posted by cjard
Yes. Use C++ if you think it will make your program better
If I were to be having it done in C++, then I guess I wouldnt be exploring the possibilities in C#. When someone is learning a new language, its only a human tendancy to try and relate to what they already know and see if its the same in the new one or if its different.
Quote:
Originally Posted by cjard
Get typing code, not posts
sure thing.. thanks for the suggestion...discussion forums I thought were places wherein you could get answers to your questions, which was why I sought help here.. !! And I guess in forums, you post not code, to seek answers !!
Maybe I was wrong !! Anyways... !!!
-
Re: Diamond Inheritance Problem - C#
Quote:
Originally Posted by hakuna_matata
When someone is learning a new language, its only a human tendancy to try and relate to what they already know and see if its the same in the new one or if its different
This is one of the biggest pitfalls in going from one language to a comletely different one that has similar (but distinctly different) usage.
There is alot of very good C++ code, that you can copy over to C# and it will compile and run. However it will be very bad code.
When I train people in .NET I avoid this by always training C++ programmers in VB.NET and VB 6.0 programmers in C#. This helps break the habits of the old language.
Consider the following:
Code:
class MyClass
{
public MyClass(int x) { m_x = x}
~MyClass() {}
public int Calc(int y) { return m_x = y; }
private int m_x;
}
There is a MAJOR flaw in this class that will cripple system performance (slowing it down by up to a factor of 10!). However I see exactly this type of construct in code written by people that learn C++.
I strongly recommend that you make a concerted attempt to FORGET (or at least IGNORE) EVERYTHING you know about C++. Get a good C# book and start from scratch just as if you have never programmed before.
The primary reason (in my professional experience as a consultant) that many .NET applications have poor performance is directly attributable to developers bringing over patterns and practices that served them well in their previous environment, but have absolutely no place in .NET
-
Re: Diamond Inheritance Problem - C#
Well, .NET certainly don't support multiple inheritance, but by using a wrapper class you can solve the problem:
Code:
class AllRounderWrapper : Bowler
{
class AllRounderInsider : Batsman
{
}
}
Altought it's recommended to use interfaces instead.
And besides, I can't see why what you're doing is good for. Maybe the upsidedown proccess will be useful: derive from Batsman & Bowler from a base class, as you acually already did in the code above.
-
Re: Diamond Inheritance Problem - C#
Quote:
Originally Posted by TheCPUWizard
This is one of the biggest pitfalls in going from one language to a comletely different one that has similar (but distinctly different) usage.
There is alot of very good C++ code, that you can copy over to C# and it will compile and run. However it will be very bad code.
When I train people in .NET I avoid this by always training C++ programmers in VB.NET and VB 6.0 programmers in C#. This helps break the habits of the old language.
Consider the following:
Code:
class MyClass
{
public MyClass(int x) { m_x = x}
~MyClass() {}
public int Calc(int y) { return m_x = y; }
private int m_x;
}
There is a MAJOR flaw in this class that will cripple system performance (slowing it down by
up to a factor of 10!). However I see exactly this type of construct in code written by people that learn C++.
I strongly recommend that you make a concerted attempt to FORGET (or at least IGNORE) EVERYTHING you know about C++. Get a good C# book and start from scratch just as if you have never programmed before.
The primary reason (in my professional experience as a consultant) that many .NET applications have poor performance is directly attributable to developers bringing over patterns and practices that served them well in their previous environment, but have absolutely no place in .NET
What design flaw you are talking about exactly ?
-
Re: [RESOLVED] Diamond Inheritance Problem - C#
The empty destructor.
This will cause the object to be processed through the Garbage Collector, and can slow down performance the the application by a factor of over 1000! (e.g. 10 Seconds rather than 0.01 sections. :eek: )
-
Re: [RESOLVED] Diamond Inheritance Problem - C#
Quote:
Originally Posted by TheCPUWizard
The empty destructor.
This will cause the object to be processed through the Garbage Collector, and can slow down performance the the application by a factor of over 1000! (e.g. 10 Seconds rather than 0.01 sections. :eek: )
Can you please elaborate on this one?
-
Re: [RESOLVED] Diamond Inheritance Problem - C#
I assume he means in the absolute worst case scenario when you are creating 1000's of objects a second all of which have empty destructors. I've no interest in even attempting to benchmark that scenario though ;)
-
Re: [RESOLVED] Diamond Inheritance Problem - C#
My bad... I read it wrongly... I was reading it as if it was a constructor.. rather than reading it correctly as a destructor..
Yup now I get the point ! and yeah I agree too... coz C++ gave the responsibility of doing memory cleanup to the programmer himself, an empty destructor prolly didnt make much of a deal, but since Java and C# have their own garbage collectors, I guess it does add an overhead on the part of the garbage collector to call the destructors of all the objects...
Question cleared.... :)
-
Re: [RESOLVED] Diamond Inheritance Problem - C#
Quote:
Originally Posted by Mutant_Fruit
I assume he means in the absolute worst case scenario when you are creating 1000's of objects a second all of which have empty destructors. I've no interest in even attempting to benchmark that scenario though ;)
Actually over 38K per second, dropping to 1.5K with a finalizer.
Also remember that every LIVE object takes GC resources. DEAD objects do not. Therefore if can be faster to create/destory thousands of objects then it is to keep references to a few hundred.
This contradicts many (good) C++ designs where items are cached that will be (or even might be) used later.
Even a "null" member of a class can induce performance (time) overhead.
I consulted on a graphics analysis program about a year ago where the performance was far below expectations [22 seconds to run one analysis]. A quick analysis showed that over 30% of the time was spent in garbage collection.
Refstructuring the code so that objects were created/used/abandoned as quick as possible, and that no extranious reference variables were in existance reduced the GC time to under 2% of the application time. The total time per analysis was reduced to just over 9 seconds.
-
Re: [RESOLVED] Diamond Inheritance Problem - C#
we can use interface to solve diamond problem .
interface player
{
void testplayer();
}
interface batsman : player
{
void testbatsman();
}
interface bowler : player
{
void testbowler();
}
interface allrounder : batsman, bowler
{
void testallrounder();
}
public class sachin : allrounder
{
void player.testplayer()
{
Console.WriteLine("test player");
}
void batsman.testbatsman()
{
Console.WriteLine("test batsman");
}
void bowler.testbowler()
{
Console.WriteLine("test bowler");
}
void allrounder.testallrounder()
{
Console.WriteLine("test allrownder");
}
}
the interface can inherit more than two interface and class can inherit the interface which inherit more than two class . obviously you problem solved. some thing like above code .
-
1 Attachment(s)
Re: [RESOLVED] Diamond Inheritance Problem - C#
@gunasekaranmca: This thread is from 2008 - it is generally not encouraged to revive old threads; but, since you did, and I didn't notice and made a sample demo project (...), I think it might be helpful to you and others who might be searching the forums if I post it.
About the original question: To clarify things, the main thing people don't understand when it comes to the diamond inheritance in C# is how to avoid writing duplicate code, if they need to have implementations of classes on every level of the hierarchy. The answer is rather simple - encapsulate the common behaviors (or implementations) into another class, and use composition. IIRC, it was in the Go4 book that they said "composition is a flexible alternative for inheritance".
This is entirely a design question - C#'s restriction to single implementation inheritance is precisely imposed to avoid various problems and bugs associated with multiple inheritance - diamond problem among them. However, since it allows multiple interface inheritance, it is possible to create a diamond-shaped inheritance ("is-a") hierarchy in C#; furthermore, the classical diamond problem ("which implementation should be inherited") is non-existent here.
Forget about C# interface types for the moment. As you probably know, the in language-independent context, in OOP the term "(public) interface" simply denotes the set of all public members of a type, which other types can use when they need to interact. Now, C# interface type, aside from defining a new type, represents a contract of sorts, with respect to anything that implements it. A class which implements an interface is simply saying: "I hereby declare that I will provide implementations of such and such public methods, properties, etc..." (to put it that way). These implementations can come from wherever - the interface type doesn't care.
So, they can come from other objects. In OOP, classes and objects can be used to represent anything - not just some real world thing with various attributes; they can represent imaginary concepts, constructs purely designed for programming-tasks, they can even represent behaviors (which can then be dynamically replaced), and so on. An implementation class can represent a part of the implementation of some other class, and an instance of the implementation class can then be composed into another object to provide that implementation. This also means that it can be shared (the implementation, not the object itself, although that's also possible), so code duplication is avoided.
It may all sound complicated, but it really isn't, as you'll see from the sample attached.
Essentially, in the sample, there are four interfaces: A, B, C, D (for this particular occasion, I temporarily abandoned the usual "I" prefix for interfaces, since IA, IB, etc... might be somewhat distracting and harder to read).
To form the diamond shaped hierarchy, B and C inherit A, and then D inherits B and C. Then for classes implement these iterfaces - ConcreteA, ConcreteB, ConcreteC and ConcreteD. The implementation for, say, A, is extracted and encapsulated into another class, called AImpl, an instance of which is then referenced from all other classes. This way, the implementation for A is written only once. Similar approach is used for B and C. Some comments in the example provide additional explanations. It's a VS2010 project (console app).