在派生类中指定字段类型

问题描述

出于向后兼容的原因,我有一个Rectangle2d和一个Rectangle3d。这样做时,类的“ transform”字段的类型应从Transform2d更改为Transform2d的派生版本Transform3d。 这是一个简化的示例:

class Transform2
{
    protected float positionX;
    protected float positionY;
}

class Transform3 : Transform2
{
    protected float positionZ;
}


class Rectangle2d
{
    protected Transform2 transform;
}

class Rectangle3d : Rectangle2d
{
    // Does not work: Just hides Rectangle2d.transform
    protected new Transform3 transform;
}

我不喜欢的一种解决方案是不使用Transform类,而直接使用字段:

class Rectangle2d
{
    protected float positionX;
    protected float positionY;
}

class Rectangle3d : Rectangle2d
{
    protected float positionZ;
}

在我眼中,当第二种方法有效并且第一种方法只是第二种方法并带有一些聚束时,应该有一个干净的解决方案。至少希望如此。

版本:.NET Framework 4.6.1

解决方法

继承表示is-a关系。 Rectangle3d不是2d,因此它可能不应继承自Rectangle2d

也就是说,如果必须执行此操作,建议您使用泛型

public abstract class Transform<T>
{
    protected T transform;
}

public class Rectangle2d : Transform<Transform2> {}
public class Rectangle3d : Transform<Transform3> {}

在此模型中,2d和3d均具有强类型的属性transform

,

您要的是不可能的,不能覆盖字段。这是设计准则不鼓励公开(且protected公开)字段的部分原因。不过,您可以将其抽象为属性:

class Rectangle2d
{
    private Transform2d transform;

    protected virtual Transform2d Transform => transform;
} 

class Rectangle3d
{
    private Transform3d transform;

    protected override Transform2d Transform => transform;
} 

理想情况下,基类应尽可能少地依赖具体的transform字段,而应使用Transform属性。但是,作为设计建议,请考虑将常见行为抽象到abstract RectangleBase中,并让2D和3D变体从其继承,而不是彼此继承。您现在正沿着Rectangle2d来创建相当脆弱的基类。