C# 从派生类更改基类的正确方法

C# 从派生类更改基类的正确方法,c#,inheritance,design-patterns,C#,Inheritance,Design Patterns,我正在尝试设计几个基本的绘图类,从中可以继承和定义复杂的绘图 public abstract class Drawing { public bool CanBeRotated { get; set; } private float m_rotation; public float Rotation { get { return m_rotati

我正在尝试设计几个基本的绘图类,从中可以继承和定义复杂的绘图

public abstract class Drawing
{       
    public bool CanBeRotated 
    {
       get; 
       set;
    }

    private float m_rotation;
    public float Rotation
    {
        get 
        { 
           return m_rotation;
        }
    }

    protected Drawing()
    {
        CanBeRotated = true;
    }

    public void Rotate(float degree)
    {
        if (CanBeRotated)
            m_rotation = degree;
    }
}

public sealed class LineDrawing : Drawing
{
    private readonly Line m_line;

    public Line Line
    {
        get
        {
           return m_line;
        }
    }

    public LineDrawing(Line line)
    {
        m_line = line;
    }
}

public class CompoundDrawing : Drawing
{
    protected IList<Drawing> m_drawings;

    protected CompoundDrawing(IList<Drawing> drawings)
    {
        m_drawings = new List<Drawing>(drawings);
    }
}
如您所见,
LineDrawing
CompoundDrawing
派生自抽象绘图类。
CompoundDrawing
有一个内部的
列表
,允许我们存储所需数量的
Drawing
对象,并定义更复杂的图形

public abstract class Drawing
{       
    public bool CanBeRotated 
    {
       get; 
       set;
    }

    private float m_rotation;
    public float Rotation
    {
        get 
        { 
           return m_rotation;
        }
    }

    protected Drawing()
    {
        CanBeRotated = true;
    }

    public void Rotate(float degree)
    {
        if (CanBeRotated)
            m_rotation = degree;
    }
}

public sealed class LineDrawing : Drawing
{
    private readonly Line m_line;

    public Line Line
    {
        get
        {
           return m_line;
        }
    }

    public LineDrawing(Line line)
    {
        m_line = line;
    }
}

public class CompoundDrawing : Drawing
{
    protected IList<Drawing> m_drawings;

    protected CompoundDrawing(IList<Drawing> drawings)
    {
        m_drawings = new List<Drawing>(drawings);
    }
}
公共抽象类绘图
{       
公共布尔堪培拉酒店
{
得到;
设置
}
私人浮动m_旋转;
公众浮标轮换
{
得到
{ 
返回m_旋转;
}
}
受保护的图形()
{
堪培拉=真;
}
公共空心旋转(浮动度)
{
如果(堪培拉)
m_旋转=度;
}
}
公共密封类线条图:图形
{
专用只读线路m_线;
公用线路
{
得到
{
返回m_线;
}
}
公共线条图(线条)
{
m_线=线;
}
}
公共类复合绘图:绘图
{
受保护的IList m_图纸;
受保护的复合图纸(ILST图纸)
{
m_图纸=新列表(图纸);
}
}
假设我想定义一个从CompoundDrawing派生的矩形图形

public class RectangleDrawing : CompoundDrawing
{
    public RectangleDrawing(IList<LineDrawing> lineDrawings) : base(lineDrawings)
    {
        foreach(var line in lineDrawings)
        {
            line.CanBeRotated = false;
        }
    }    
}
公共类矩形绘图:复合绘图
{
公共矩形图形(IList线条图形):基础(线条图形)
{
foreach(线条图中的var线条)
{
line.CanBeRotated=false;
}
}    
}

现在我面临一个问题!显然,我不希望这个新类中的线条绘制对象是可旋转的!但我不确定在这个模式中我应该设置在哪里
public abstract class Drawing
{ 
    //some shapes might not be rotable or rotation
    //simply doesn't make sense: circle      
    public virtual bool CanBeRotated => true;

    public Drawing Rotate(float degree)
    {
        //Don't mutate this, return a new
        //rotated instance.
        if (!CanBeRotated) return this;
        return rotate(float);
    }

    //let each concrete type handle its own rotation.
    protected abstract Drawing rotate(float);

    //etc.
}
不变性给你买了什么?好吧,谁在乎有人试图旋转你的复合对象的单独线条?它们不会改变任何重要的东西,因为任何东西都不会改变,它们只会获得一条不属于原始复合对象的新旋转线

CompoundDrawing
旋转逻辑将非常简单:

protected override Drawing rotate(float degeee)
   //Note I'm passing in an IEnumerable<Line> instead of an IList<>
   //Why the need of an IList<>, don't burden the API with unecessary 
   //constraints.
    => new Rectange(lines.Select(l => l.Rotate(degree)));
protected override图形旋转(浮动degeee)
//注意,我传递的是IEnumerable而不是IList
//为什么需要一个IList,而不是让API承担不必要的负担
//限制。
=>newrectange(lines.Select(l=>l.Rotate(度));

综上所述,我建议您将构建块更改为
似乎是一个奇怪的选择。这样,所有形状都是按特定顺序由点组成的复合图形。绘制任何形状只是按顺序连接点,旋转只是旋转每个点,等等。

我将旋转移动到它自己的界面,因为它不适用于所有类型的绘制

public interface IRotate
{
    void Rotate(float degree);
}

public class SquareDrawing : Drawing, IRotate
{
    public void Rotate(float degree)
    {
         //actual code to rotate the drawing
    }
}

public class RectangleDrawing : CompoundDrawing
{
     public RectangleDrawing(IList<LineDrawing> lineDrawings) : base(lineDrawings)
     {
        foreach(var line in lineDrawings)
        {
            if (line is IRotate)
            {
                 ((IRotate)line).Rotate(45.0);
            }
        }
     }    
}
公共接口IRotate
{
空隙旋转(浮动度);
}
公共类方形绘图:绘图,旋转
{
公共空心旋转(浮动度)
{
//旋转图形的实际代码
}
}
公共类矩形绘图:复合绘图
{
公共矩形图形(IList线条图形):基础(线条图形)
{
foreach(线条图中的var线条)
{
如果(线是旋转的)
{
((旋转)线)。旋转(45.0);
}
}
}    
}

所以你不想旋转
矩形绘图
或组成线段?@BradleyDotNET线段!我想您只需要对
lineDrawings
进行一次处理,然后设置它们的
CanBeRotated
属性。或者更改您的继承模型,使每个类始终是可旋转的或不可旋转的。那又怎样?你还在写这门课。如果您的基本问题是“派生类能否接触基类成员”,那么答案是响亮的“是”。您仍然需要旋转线条才能旋转矩形。如果将属性设置为
false
,则在旋转矩形时需要将其临时重置为
true
。我认为你的整个计划太复杂了,它对你不利,而不是帮助你。