1

假设我们的应用程序中有几个操作。因此,我们创建一个AbstractActionand,例如,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

4 回答 4

4

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

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


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

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

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

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

于 2013-06-19T07:53:13.940 回答
3

我还会质疑为什么你的基类中需要一个 ActionType ?这样是不是你的基类可以根据 ActionType(即派生类的类型)有不同的行为?如果是这样,那么更好的设计是使用多态性,即去掉 actionType 属性,并在基类中提供抽象方法,在派生类中重写这些方法以实现派生类的特定行为。

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

于 2013-06-19T08:13:56.570 回答
2

如果所有动作都有 actionType 它应该在基类中。没有太大的区别,但我也会考虑可读性和简单性。顺便说一句,我不会有 2 节课,只有一节课。如果 actionType 仅特定于 ActionMove,则 actionType 应该在 ActionMove 中。

于 2013-06-19T07:48:16.207 回答
1

我会同意你的。由于ActionType是从AbstractAction继承的所有类的公共属性,因此应该在AbstractAction构造函数中设置它。

于 2013-06-19T07:49:41.070 回答