Home > Enterprise >  Optional use of base constructor C#
Optional use of base constructor C#

Time:08-16

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.

  • Related