简体   繁体   中英

Specify field type in derived class

I have a Rectangle2d and a Rectangle3d deriving from it for backward compatibility reasons. In doing so, the type of the class' "transform" field shall change from Transform2d to Transform3d which is a derived version of Transform2d. Here's a simplified example:

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;
}

One solution I do not prefer is going without a Transform class and direct fields instead:

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

class Rectangle3d : Rectangle2d
{
    protected float positionZ;
}

In my eyes, when the second method works and the first method is just the second method with some bunching, there should be a clean solution for it. At least it hope so.

version: .NET Framework 4.6.1

Inheritance implies an is-a relationship. Rectangle3d is not 2d, so it should probably not inherit from Rectangle2d

That said, If you must do this I suggest you use generics

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

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

In this model both 2d and 3d have a property transform which is strongly typed.

What you're asking for is impossible, fields cannot be overriden. This is part of the reason why publicly visible (and protected is publicly visible) fields are diacouraged by design guidelines. You can abstract it into a property, though:

class Rectangle2d
{
    private Transform2d transform;

    protected virtual Transform2d Transform => transform;
} 

class Rectangle3d
{
    private Transform3d transform;

    protected override Transform2d Transform => transform;
} 

Ideally your base class should rely as little as possible on the concrete transform field and instead use the Transform property. However, as a design suggestion, consider abstracting common behaviour into an abstract RectangleBase and have the 2D and 3D variants inherit from it, not from each other. You're on a path of creating a rather brittle base class out of Rectangle2d as is now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM