在派生中指定字段类型 class
Specify field type in derived class
出于向后兼容的原因,我有一个 Rectangle2d 和一个派生自它的 Rectangle3d。这样做时,class'“转换”字段的类型应从 Transform2d 更改为 Transform3d,它是 Transform2d 的派生版本。
这是一个简化的例子:
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;
}
我不喜欢的一个解决方案是不使用转换 class 而是直接字段:
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;
}
理想情况下,您的基础 class 应该尽可能少地依赖具体的 transform
字段,而是使用 Transform
属性。然而,作为一个设计建议,考虑将常见行为抽象为 abstract
RectangleBase
并让 2D 和 3D 变体继承它,而不是相互继承。您正像现在一样从 Rectangle2d
中创建一个相当脆弱的基础 class。
出于向后兼容的原因,我有一个 Rectangle2d 和一个派生自它的 Rectangle3d。这样做时,class'“转换”字段的类型应从 Transform2d 更改为 Transform3d,它是 Transform2d 的派生版本。 这是一个简化的例子:
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;
}
我不喜欢的一个解决方案是不使用转换 class 而是直接字段:
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;
}
理想情况下,您的基础 class 应该尽可能少地依赖具体的 transform
字段,而是使用 Transform
属性。然而,作为一个设计建议,考虑将常见行为抽象为 abstract
RectangleBase
并让 2D 和 3D 变体继承它,而不是相互继承。您正像现在一样从 Rectangle2d
中创建一个相当脆弱的基础 class。