i'm new to C#. I learned that a derived class can have only one base class. In my opinion this is a weakness of C#, but maybe I don't get it right. I'm looking for "the best" solution to get around this while respecting the DRY and clean code principles. Below I created an example where I finally derived from two classes to show the idea. There are two obvious solutions to this:
- Implement the members and methods of
CColor
twice intoCColoredRectangle
andCColoredTriangle
. But this violates the DRY principle - Implement the members and methods of
CColor
intoCShape
(or derive aCColoredShape
class as base for the others). But then theCColor
methods are available inCRectangle
andCTriangle
where they are not supposed to exist. This breaks with the clean code idea.
Interfaces won't do the job as they dont allow members. Is there any elegant solution to this? Thanks in advance.
public abstract class CShape
{
private double x,y;
protected CShape(double x, double y)
{
this.x = x;
this.y = y;
}
public abstract double Area { get; }
public class CRectangle : CShape
{
protected CRectangle(double x, double y) : base(x, y) { }
public override double Area => x * y;
}
public class CTriangle : CShape
{
protected CTriangle(double x, double y) : base(x, y) { }
public override double Area => x * y * 0.5;
}
public class CColor
{
public int R,G,B; //I need members here, so an interface won't work
public void MixColorWith(int r,int g,int b) { /*Code....*/}
}
public class CColoredTriangle : CTriangle, CColor //compiler error CS1721
{
}
public class CColoredRectangle : CTriangle, CColor //compiler error CS1721
{
}
}
CodePudding user response:
I learned that a derived class can have only one base class. In my opinion this is a weakness of C# [...]
Let's go over what things are correct, in your opinion, to be able to quantify the statement that this is a weakness of C#, again in your opinion.
You posit that a colored triangle is a color. That's what inheritance means, it's an "is-a" relationship. And while there exist some colors that aren't colored triangles, you posit that at least some colors are colored triangles. Are we on the same page here?
So here's my opinion: there doesn't exist a single color that's a colored triangle. There is no "is-a" relationship here at all. You might be able to make a case for the fact that colored triangles "have-a" color, in which case you would add a Color
property to it, but nothing more.
So there you go, diamond (multiple) inheritance is not needed for your problem.
Edit: Also the other thing you posit, "I need members here, so an interface won't work", is just plain wrong, on both accounts. Interfaces can have both properties and methods in C#.
CodePudding user response:
Generally, most pundits say you should "Prefer composition over inheritance".
And in this case, that is almost certainly the right thing to do.
A CColoredTriangle
isn't a CColor
, it has a CColor
, and therefore it should just be a property of it.
Given that you seem to also want to be able to refer to objects just by the fact that they have a CColor
, irrespective of what they Shape they are, it makes sense to create an IHasColor
interface
public abstract class CShape
{
private double x,y;
protected CShape(double x, double y)
{
this.x = x;
this.y = y;
}
public abstract double Area { get; }
public class CRectangle : CShape
{
protected CRectangle(double x, double y) : base(x, y) { }
public override double Area => x * y;
}
public class CTriangle : CShape
{
protected CTriangle(double x, double y) : base(x, y) { }
public override double Area => x * y * 0.5;
}
public class CColor
{
public int R,G,B;
public void MixColorWith(int r,int g,int b) { /*Code....*/}
}
public interface IHasColor
{
CColor Color {get; set;}
}
public class CColoredTriangle : CTriangle, IHasColor
{
CColor Color {get; set;}
}
public class CColoredRectangle : CTriangle, IHasColor
{
CColor Color {get; set;}
}
}