【问题标题】:Use instanceof or public method to get instance使用 instanceof 或 public 方法获取实例
【发布时间】:2013-05-10 08:50:37
【问题描述】:

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

所以我的问题是:

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

提前致谢

【问题讨论】:

  • 使用的实例更加通用和可读。
  • 感谢您的回复和回答。为那些回答的人提供更多信息:正在做的事情是,如果它是一个组,则需要将其添加到数据库表中的不同字段

标签: java polymorphism subclass instanceof


【解决方案1】:

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

通常,使用instance of 表示您的模型有问题。

如果你需要对不同的子类型有不同的行为,这意味着你并没有真正使用父类型。此外,你不得不知道实现细节,这不应该是这样的。

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

【讨论】:

    【解决方案2】:

    这正是您应该使用instanceOf 运算符的地方。

    instanceof 运算符将对象与指定类型进行比较。你 可以用它来测试一个对象是否是一个类的实例,一个实例 一个子类,或一个实现特定的类的实例 界面。

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

    您也可以使用GroupItem.class.isInstance(items[0]) 进行检查。喜欢-

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

      • 这是因为如果 Item 是一个 group item 它需要添加到某些字段,如果不是那么它会转到一个 db 中的其他字段
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        我选择的解决方案让我不必担心对象是什么子类型(感谢 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();
        
                   ...
              }
         }
        

        再次感谢大家。

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

        【讨论】:

          猜你喜欢
          • 2011-01-06
          • 2015-02-24
          • 1970-01-01
          • 1970-01-01
          • 2013-01-13
          • 2019-01-24
          • 1970-01-01
          • 2011-09-22
          • 1970-01-01
          相关资源
          最近更新 更多