假设我们在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)
{
/**/
}
他说我的变体很糟糕,尽管他不能说出原因。这不是说我能说它很好,它对我来说感觉很合适。所以,你能告诉我哪种方式更好,为什么?或者可能有第三种方式?
答案 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 构造函数中设置。