简体   繁体   English

instanceof vs布尔类型检查

[英]instanceof vs boolean type checking

I have an interface called Section and MapSection which extends section. 我有一个名为Section和MapSection的接口,它扩展了section。 I have a list of Sections and if it is a MapSection I need to do some additional processing. 我有一个Sections列表,如果它是MapSection,我需要做一些额外的处理。 I can thing of two ways to handle this. 我可以通过两种方式处理这个问题。 I can add a boolean isAMapSection() to the Section interface but that leads to alot of isA.. if I add more types. 我可以在Section接口中添加一个布尔值isAMapSection()但是如果我添加更多类型,则会导致很多isA .. The other way I could think of is instanceof check but my OOP senses think this is not great either. 我能想到的另一种方式是检查实例,但我的OOP感觉认为这也不是很好。

curSection instanceof MapSection

which one of these is the right way? 哪一个是正确的方法? or is there another way? 还是有另一种方式?

As mentioned above by Oliver Charlesworth's comment, you could use a Visitor Design Pattern to give your code to do different actions depending on the type involved, without having to use a bunch of instanceof's or class equals. 正如Oliver Charlesworth的评论所述,你可以使用访问者设计模式让代码根据所涉及的类型执行不同的操作,而不必使用一堆instanceof或class equals。

For example, say you have two similar interfaces, Section and MapSection, where for grins will give MapSection one additional method: 例如,假设您有两个类似的接口,Section和MapSection,其中grins将为MapSection提供一个额外的方法:

interface Section {
   void someMethod();
   void accept(SectionVisitor visitor);
}

interface MapSection extends Section {
   void additionalProcessingMethod();
}

We'll also give Section the accept(...) method to allow action by a Visitor of type SectionVisitor whose interface looks like: 我们还将给Section提供accept(...)方法,以允许类型为SectionVisitor的Visitor的操作,其界面如下所示:

interface SectionVisitor {
   void visit(Section section);
   void visit(MapSection mapSection);
}

The visit method will hold code that knows which methods to call depending on the type passed into it. visit方法将保存代码,该代码根据传入的类型知道调用哪些方法。

A very simple concrete example could look like: 一个非常简单的具体示例可能如下所示:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class VisitorTest {
   public static void main(String[] args) {
      Random random = new Random();
      List<Section> sectionList = new ArrayList<>();
      for (int i = 0; i < 10; i++) {
         Section section = random.nextBoolean() ? new ConcreteSection() : new ConcreteMapSection();
         sectionList.add(section);
      }

      SectionVisitor visitor = new ConcreteSectionVisitor();
      for (Section section : sectionList) {
         section.accept(visitor);
      }
   }
}

interface Section {
   void someMethod();
   void accept(SectionVisitor visitor);
}

interface MapSection extends Section {
   void additionalProcessingMethod();
}

interface SectionVisitor {
   void visit(Section section);
   void visit(MapSection mapSection);
}

class ConcreteSection implements Section {

   @Override
   public void someMethod() {
      System.out.println("someMethod in ConcreteSection");
   }

   @Override
   public void accept(SectionVisitor visitor) {
      visitor.visit(this);
   }

}

class ConcreteMapSection implements MapSection {

   @Override
   public void someMethod() {
      System.out.println("someMethod in ConcreteMapSection");
   }

   @Override
   public void additionalProcessingMethod() {
      System.out.println("additionalProcessingMethod in ConcreteMapSection");
   }

   @Override
   public void accept(SectionVisitor visitor) {
      visitor.visit(this);
   }

}

class ConcreteSectionVisitor implements SectionVisitor {

   @Override
   public void visit(Section section) {
      section.someMethod();
   }

   @Override
   public void visit(MapSection mapSection) {
      mapSection.someMethod();
      mapSection.additionalProcessingMethod();
   }

}

Best way might be to add a method "additionalProcessing" to Section. 最好的方法可能是在Section中添加一个方法“additionalProcessing”。 Implement this method to do your additional processing in MapSection, and leave it blank in your other implementations 实现此方法以在MapSection中执行其他处理,并在其他实现中将其留空

Sometimes it's fine to have an isXXX method (and the corresponding asXXX method is nice too), but it really depends on how open-ended your object hierarchy is. 有时候使用isXXX方法(并且相应的asXXX方法也很好)也asXXX ,但它实际上取决于对象层次结构的开放性。

For example in StAX the XMLEvent interface will have descendants that represent the different types of events that can come from an XML document. 例如,在StAX中, XMLEvent接口将具有后代,这些后代表示可以来自XML文档的不同类型的事件。 But the list of those types is closed (no-one's going to radically change the XML format any time soon) and very short (there are about 10 different types of events in the StAX API), so it's fine. 但是这些类型的列表是封闭的(没有人会在短期内彻底改变XML格式)而且很短(StAX API中有大约10种不同类型的事件),所以没关系。 These interfaces also define the primary nature of their implementations, you wouldn't realistically just tag an object with an XMLEvent interface like you do with Serializable or Iterable . 这些接口还定义了它们的实现的主要特性,您不会像使用SerializableIterable那样用XMLEvent接口标记对象。

If your interface is more "behavioural" (for want of a better word), more optional (like Comparable ) or too open-ended (like LayoutManager ), things like the visitor or the strategy pattern may be more appropriate. 如果您的界面更“行为”(因为缺少更好的词),更多可选(如Comparable )或过于开放(如LayoutManager ),访问者或策略模式等内容可能更合适。

Judging just by the names Section and MapSection , your model seems to belong to the first category but really only you can make that decision. 仅通过名称SectionMapSection ,您的模型似乎属于第一类,但实际上只有您可以做出决定。 What I definitely wouldn't do is leave it to the client of the code to fool around with instanceof calls. 我绝对不会做的是将它留给代码的客户端来使用instanceof调用。 One way or another the solution should be part of Section . 这种或那种解决方案应该是Section一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM