使用instanceof或public方法获取实例

时间:2013-05-10 08:50:37

标签: java polymorphism subclass instanceof

所以我有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 ...
           } 
      }
 }

所以我的问题是:

  • instanceof or method?
  • if item,in Item or Promotion?
  • ,为什么? (这样我可以更好地理解推理)

提前致谢

5 个答案:

答案 0 :(得分:3)

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

通常,使用instance of表示模型中存在错误。

如果您需要针对不同的子类型使用不同的行为,则表示您实际上并未使用父类型。此外,您不得不知道实现细节,但情况并非如此。

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

答案 1 :(得分:2)

这是您应该使用instanceOf运算符的确切位置。

  

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

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

您也可以使用GroupItem.class.isInstance(items[0])来检查相同内容。喜欢 -

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

答案 2 :(得分:1)

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

假设是决定一个项目是否有资格参加促销活动,促销规则可​​能会改变:那么我会使用instanceof,因为您不希望促销规则逻辑“污染”您的基本对象。

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

答案 3 :(得分:1)

instaceOf运算符是更好的选择,但我也会考虑使用Visitor pattern

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());
    }
}

答案 4 :(得分:0)

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

我选择的解决方案让我甚至不会被对象的子类型所困扰(感谢Assylias和BalázsMáriaNé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();

           ...
      }
 }

再次感谢大家。

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