0

所以我有3门课:

  • Item
  • GroupItem 延伸 Item
  • ProductItem 扩展项目

我将一组Item对象传递给一个类,并希望根据它们的类类型做不同的事情。

使用instanceof是一种可接受的方法,或者我应该有一个内部boolean isGroup()方法,该方法将在指定子类的初始化时设置。

 class Item {
      protected boolean isGroup = false;
      public boolean isGroupItem() { return isGroup; }
 }

 class GroupItem extends Item {
      public GroupItem() {
           isGroup = true;
      }
 }

 class ProductItem extends Item {
      public ProductItem() {
           isGroup = false;
      }
 }


 class Promotion {
      // Item can be either a group or a list of items
      private List<Item> items = new LinkedList<Item>;
      public void addItem(Item itemObj) {
           items.addItem(itemObj);
      }
      public List<Item> getItems() {
           return items;
      }
 }



 class Checker {
      // Items retrieved from Promotion and passed from another class as array
      public Checker(Item[] items) {
           // either

           if(items[0] instanceof GroupItem) {
                // Do something ...
           }

           // or

           if(items[0].isGroupItem()) {
                // Do something ...
           } 
      }
 }

所以我的问题是:

  • 实例或方法?
  • 如果方法,在项目或促销中?
  • 而且,为什么?(只是这样我可以更好地理解推理)

提前致谢

4

5 回答 5

3

对要作为参数传递的实际类型使用不同的方法。

通常,使用instance of意味着你的模型有问题。

如果你需要对不同的子类型有不同的行为,这意味着你并没有真正使用父类型。此外,您被迫了解实现细节,这不应该是这种情况。

如果您拥有的继承只是技术继承,请尝试使用组合而不是继承

于 2013-05-10T09:00:44.400 回答
2

instanceOf这是您应该使用operator的确切位置。

instanceof 运算符将对象与指定类型进行比较。您可以使用它来测试对象是类的实例、子类的实例还是实现特定接口的类的实例。

没有必要草拟一个新方法或一些布尔属性来做这些事情。GroupItem您可以通过检查 instanceOf轻松识别特定对象。

你也可以用它GroupItem.class.isInstance(items[0])来检查。喜欢 -

if(GroupItem.class.isInstance(items[0])) {
      // Do something ...
}
于 2013-05-10T08:53:49.957 回答
1

我想我会尝试定义为什么我现在需要知道它是否是一个组。

假设要决定一个 Item 是否有资格进行促销并且促销规则可​​能会改变:那么我会使用instanceof,因为您不希望促销规则逻辑“污染”您的基本对象。

如果作为一个组是您的项目的一个重要属性并且在各种情况下都很有用(不仅仅是促销规则),我会将它包含在项目级别。

于 2013-05-10T08:55:07.387 回答
1

运营商是一个更好的instaceOf选择,但我也会考虑使用访客模式

interface Item{
   void accept(CheckerVisitor checker); 

}

class GroupItem implements Item{

    void accept(CheckerVisitor checker){
        checker.visit(this);
    }

}


class OtherItem implements Item{

    void accept(CheckerVisitor checker){
        checker.visit(this);
    }

}

class CheckerVisitor{

    void visit(GroupItem groupItem){
        //do specific things to GroupItem
    }

    void visit(OtherItem otherItem){}
}

class MyClassOfItems{
    List<Item> items = ...;
    for(Item item : items){
        item.accept(new CheckerVisitor());
    }
}
于 2013-05-10T08:56:00.630 回答
0

因此,在阅读完本文后,我为我的解决方案选择了一条不同的路径。感谢所有帮助过的人。

我选择的解决方案让我甚至不用担心对象是什么子类型(感谢 Assylias 和 Balázs Mária Németh 让我重新思考我的结构),因为我使用抽象类来获取我需要的信息。

 abstract class Item {
      public Item(...) {
           initialise();
           createSQLSegment();
      }

      protected String SQLSegment = "";
      protected abstract void createSQLSegment();
      public String getSQLSegment() {
           return SQLSegment;
      }

      ...
 }

 // Concrete class creates response
 class GroupItem extends Item {
      ...
      // Concrete method
      protected void createSQLStatement() {
           SQLStatement = "...SQL...";
      }
 }

 class ProductItem extends Item {
      ...
      // Concrete method
      protected void createSQLSegment() {
           SQLSegment = "...SQL..."
      }
 }


 class Promotion {
      // Item can be either a group or a list of items? extends Item>;
      public void addItem(Item itemObj) {
           items.addItem(itemObj);
      }
      public List<Item> getItems() {
           return items;
      }
 }



 class Checker {
      // Items retrieved from Promotion and passed from another class as array
      public Checker(Item[] items) {
           ...

           for(Item item : Items) {
                addPreparedSQLToBatch(item);
           }
      }

      private void addPreparedItemToBatch(Item item) {
           ...

           // No need to know concrete class
           SQLString += Item.getSQLSegment();

           ...
      }
 }

再次感谢大家。

欢迎评论,我一直在学习:-)

于 2013-05-10T10:16:56.277 回答