vendredi 24 mars 2017

C# How to make base constructor neccessary to call?

QUESTION

How to make base constructor neccessary to call in derrived class. When you don't implement abstract method IDE shows error message and you understand tha you should implement this:) I want to have some message when programmer doesn't call base(). Moreover if hierarchy is deep I need to call the first base class constructor. Maybe there are some workarounds that will make this call automatically or some solutions to say programmer that he need to make this call. As you can see this set method SetShapeWorker called in abstract class Shape constructor. I need to make neccessary to call this constructor in all derived classes.

Description

I have the shape. I decided to implement some alghorithms with Command pattern, so Shape is receiver. Also in this case it is an invoker, because inside some methods I need to call some methods from ShapeWorker. Here it is SizeDialog. Look at constructor in Shape, I have shapeWorker variable that methods I use inside some Shape methods - look at default implementation of SetSizeWorker().

I want to make neccessary to initialize ShapeWorker with concrete receiver - Square or Rectangle. So I declare astract SetShapeWorker and if another programmer or maybe I after some weeks add Triangle, the IDE will show message that I need tom implement protected SetShapeWorker and programmer should understand that he need to write something like this:

class Triangle : Shape {
    //adding the triangle shape worker
    public override SetShapeWorker() {
        shapeWorker = new ShapeTriangleWorker();
        shapeWorker.SetReceiver(this);
    }
}

and after this all command invoker methods should work. As you can see this set method called in abstract class Shape constructor. So I want to make neccessary to call this constructor in all derived classes.

And the reason why I make this initialization: the use of casts (receiver as Rectangle).SetSize(a,b), (receiver as Square).SetSize(a). Uncle Bob in one of the videos says that to make these casts I should be sure that cast is valid, I agree with him:) I try to do it with is private for user interface SetShapeWorker where programmer should set the concrete receiver.

THE CODE

abstract class Shape {
    private ShapeWorker shapeWorker;    
    public Shape() {
        SetShapeWorker();
    }
    private bool isSet = false;
    public IsSet {
        get {
            return isSet;
        }
    }
    public abstract int Square();
    protected abstract void SetShapeWorker();
    public void SetSizeWorker() {
        if(shapeWorker != null) {
            shapeWorker.SizeDialog();
        }
    }
}
class Square : Shape {
    private int a;
    public Square() {

    }
    public SetSize(int a) {
        this.a = a;
        isSet = true;
    }
    public override int Square() {
        return a*a;
    }
    protected override SetShapeWorker() {
        shapeWorker = new ShapeSquareWorker();
        shapeWorker.SetReceiver(this);    
    }
}
class Rectangle : Shape {
    private int a, b;
    private Rectangle() : base() {
    }
    public SetSize(int a, int b) {
        this.a = a;
        this.b = b;
        isSet = true;
    }
    public override int Square() {
        return a*b;
    }
    protected override SetShapeWorker() {
        shapeWorker = new ShapeRectangleWorker();
        shapeWorker.SetReceiver(this);    
    }
}

abstract class ShapeWorker 
{
    public Shape receiver;
    public abstract void SetReceiver(Shape receiver) {
        this.receiver = receiver;
    }
    public abstract void SizeDialog();
    public abstract int StrangeCountSquare();
    public int getDeltaSquare() {
        if(receiver.IsSet == false) {
            SizeDialog();            
            return StrangeCountSquare();
        }
    }
}
class ShapeSquareWorker {
    public override void SizeDialog() {
        int a;
        Console.WriteLine("Enter the a: ");
        Int32.TryParse(Console.ReadLine(), out a);
        (receiver as Square).SetSize(a);
    }

    public override int StrangeCountSquare() {
        return receiver.Square() + 10;
    }
}
class ShapeRectangleWorker {
    public override void SizeDialog() {
        int a, b;
        Console.WriteLine("Enter the a: ");
        Int32.TryParse(Console.ReadLine(), out a);
        Console.WriteLine("Enter the b: ");
        Int32.TryParse(Console.ReadLine(), out b);
        (receiver as Rectangle).SetSize(a,b);
    }

    public override int StrangeCountSquare() {
        return receiver.Square() + 20;        
    }
}

BTW Now I'm learning SOLID and patterns, where is the best suit place to discuss in stackoverflow? F.e. if I want to discuss about usefull ways mixing some patterns. Answer please in comment.

Aucun commentaire:

Enregistrer un commentaire