是否可以使用扩展抽象类的空子类?

时间:2012-08-02 17:54:09

标签: java abstract-class subclass

请考虑以下事项:

  public abstract class Item {
     String name;
     String description;
     //concrete getters and setters follow
  }

   public class InventoryItem extends Item {
     //empty subclass of Item 
   }

  public class CartItem extends Item {
     int quantity;
     int tax;
     //getters and setters for quantity and tax follow
  }

InventoryItem表示可供销售的商品,而CartItem表示添加到购物车的商品,因此它具有其他属性,例如数量和税金。在这种情况下,是否可以使用抽象类Item的空子类?

选项2:我们可以有一个空的Item接口。 InventoryItem将实现Item并定义名称和描述属性,并具有getter和setter。 CartItem将从InventoryItem扩展,并将数量和税收定义为属性,并具有getter和setter。

选项3:拥有Item接口会更好吗? InventoryItem将实现Item。然后我们可以有一个CartItem类,它有'一个'项和两个属性,即税和数量

2 个答案:

答案 0 :(得分:5)

我认为这个设计没有任何问题:它明确指定Item作为基础,InventoryItem / CartItem作为可实例化的类。我会将Item重命名为AbstractItem(Java类库执行此操作),以强调该类的预期用途将用作其他类的基础。

存在特定于C ++的问题,例如assignment through the base pointer,这使得非常希望使所有“非叶子”类抽象化。虽然规则并没有按字面意思转换为Java,但我认为将非叶类抽象化仍然是一个好主意,即使该类是自给自足的。这有助于您明确区分用于直接实例化的类和用于扩展的类,这有助于不熟悉您的代码库的人进行维护。

将规则更进一步,Java中的常见做法是创建所有叶类final。这是一个很好的防御规则,特别是当你的课程是不可变的时候。

编辑:就购物车中的建模项目而言,继承并非最佳选择。事实上,我认为做错了。我会让CartItem拥有Item,而不是扩展它,因为该项目不会通过放入购物车而成为另一种实体。以下是我认为应该建模的方式:

public class Item {
    String name;
    String description;
    ...
}

public class CartItem {
   Item item;
   int quantity;
   int tax;
   ...
}

答案 1 :(得分:0)

让我提供一个稍长的建议或意见,这可能会提供一些指导。

当设计是一个层次结构时,我倾向于仅通过多态来区分行为。 一般来说,我倾向于避免仅通过数据区分对象。 多年来,我甚至根据它们所拥有的变量来停止为类似结构的“数据对象”创建的继承层次结构。

我花费大部分时间的地方在于定义抽象类的公共接口表示方法,然后具有所有适用于同一接口但具有不同行为的子类。 (利斯科夫替代原则)

在这种情况下,我会考虑一个公共接口/抽象Item类,其中Item实现的层次结构在库存方式,计算税收等方面有所不同。我可以使用方法.isInCatalog()来告诉我哪里是item或者它的本质是什么,如果我必须以不同方式处理它,但我仍然会尝试将大多数项类型特定逻辑封装到其多态方法的实现中。

虽然这些类型的计算通常是在数据库上的批处理/聚合操作中而不是在单个对象中完成的,但我会在抽象级别.getTax(),. getQuantity()上进行,然后有子类有不同的行为。 (考虑NullObject重构,以避免处理空值)

这篇坚实的博客文章中概述了很少有助于这种设计的原则:

http://codebork.com/2009/02/18/solid-principles-ood.html

相关问题