I'm trying to figure out OOP in C#. I have an abstract superclass Shape
that has a constructor, that takes an array of class Point
, and 2 optional parameters: color
and filling
.
internal abstract class Shape
{
protected string color;
protected bool filled;
protected Point[] Points;
public Shape(Point[] points, string color, bool filled)
{
this.color = color;
this.filled = filled;
if (points.Length < 3)
{
throw new Exception("A shape can't be created with less than a 3 points");
}
this.Points = points;
}
public Shape(Point[] points)
{
this.color = "green";
this.filled = true;
if (points.Length < 3)
{
throw new Exception("A shape can't be created with less than a 3 points");
}
this.Points = points;
}
}
Point
is another class that has fields for x
and y
and basically represents a point on a coordinates scale. Can be created with 2 numbers for x and y, or with another instance of Point
internal class Point
{
int x;
int y;
public Point( int x, int y)
{
this.x = x;
this.y = y;
}
public Point(Point test)
{
this.x = test.x;
this.y = test.y;
}
}
Now I need to create another class Triangle
, inherited from Shape
that can take not an array of Point
, but 3 separate instances of Point
, and then optionally take color
and filled
.
So, I was trying to do something like this:
internal class Triangle : Shape
{
Point point1;
Point point2;
Point point3;
public Triangle(Point point1, Point point2, Point point3, string color, bool filled) : base(color, filled)
{
this.point1 = point1;
this.point2 = point2;
this.point3 = point3;
}
}
The idea here is that Triangle
, if initialized with color
and filling
should override the inherited ones, otherwise should implement the logic from a parent class and basically fall to default values.
I got an error, and Visual Studio suggests me to add another constructor to Shape
that would do this:
public Shape(string color, bool filled)
{
this.color = color;
this.filled = filled;
}
Would this be the right thing to do? I just have a feeling that adding another constructor for each case kinda undermines the principles of code reuse, and there should be a better and more elegant solution. Looking around at SO didn't help me find an actual answer.
What would be a good practice/the best solution here?
CodePudding user response:
There's no need to redefine the three points that form a triangle: the Shape class can already save those, namely in its points array.
So initialize that array and pass it to the parent:
class Triangle : Shape
{
public Triangle(Point point1, Point point2, Point point3, string color, bool filled)
: base(new [] { point1, point2, point3 }, color, filled)
{
}
}
Then when you want to do something with the points within the triangle, you just use base.points[0]
, [1]
and [2]
respectively.
This illustrates the problem the compiler informs you about: you need to call an existing base constructor. There's no base constructor without a points array, so the IDE suggests to generate one. But that's not what you actually want.