在基类和派生类中初始化基类属性

时间:2013-06-19 07:42:55

标签: c# inheritance architecture

假设我们在appplication中有几个动作。因此,我们创建了AbstractAction,例如,ActionMove将继承AbstractAction

class AbstractAction
{
    /* stuff common for all actions */
    public ActionType actionType;

    public AbstractAction(Unit owner)
    {
        this.owner = owner;
    }
}

class ActionMove : AbstractAction
{
    public ActionMove(Unit owner, Vector3 destination) : base(owner)
    {
        /**/
    }
}

现在,我和我的同事发生争执。他认为actionType应该在ActionMove构造函数中分配:

public ActionMove(Unit owner, Vector3 destination) : base(owner)
{
    actionType = ActionType.Move;
    /**/
}

我认为AbstractAction构造函数应该设置将由派生类构造函数提供的操作类型:

public AbstractAction(ActionType actionType, Unit owner)
{
    this.actionType = actionType;
    this.owner = owner;
}

public ActionMove(Unit owner, Vector3 destination) : base(ActionType.Move, owner)
{
    /**/
}

他说我的变体很糟糕,尽管他不能说出原因。这不是说我能说它很好,它对我来说感觉很合适。所以,你能告诉我哪种方式更好,为什么?或者可能有第三种方式?

4 个答案:

答案 0 :(得分:4)

我同意其他答复者,如果它是所有操作的公共属性,则应在基类中分配ActionType。这似乎是一个关注点分离的简单问题:如果基类定义了属性,那么最好的做法是让基类处理它。除非有特殊原因要求您从派生类中设置该属性,否则我甚至建议将其设置为私有。

请注意,通过要求在基类构造函数中提供操作类型,可以避免在创建新派生类时忘记设置类型。然后,基础构造函数将强制您提供它并为您设置它。


另一种解决方案可能是定义一个抽象属性,然后在派生类中实现它。

abstract class AbstractAction
{
    public abstract ActionType actionType { get; }
}

class ActionMove : AbstractAction
{
    public override ActionType actionType
    {
        get { return ActionType.Move; }
    }
}

此解决方案还确保所有派生类都实现该属性,因为当您不实现抽象属性时,您将收到编译器警告。

答案 1 :(得分:3)

我还会质疑你为什么需要基类中的ActionType?这是否因此您的基类可以具有不同的行为,具体取决于ActionType(即派生类的类型)?如果是这样,那么更好的设计是使用多态,即摆脱actionType属性,并在基类中提供抽象方法,在派生类中重写它以实现派生类特定的行为。

我很欣赏这是一个有点人为的例子,因此我的评论可能不适用于您的真实代码。

答案 2 :(得分:2)

如果所有Actions都有actionType,那么它应该在基类中。没有太大的区别,但我也会考虑可读性和简单性。顺便说一句,我不会有两个班级。如果actionType仅特定于ActionMove,则actionType应位于ActionMove中。

答案 3 :(得分:1)

我同意你的看法。由于 ActionType AbstractAction 所有类的公共属性,因此应在 AbstractAction 构造函数中设置。