【问题标题】:how to check if an instance of an abstract object belongs to a particular subclass如何检查抽象对象的实例是否属于特定的子类
【发布时间】:2019-06-04 19:33:03
【问题描述】:

我在这里引用了这个重复的问题:
Check if a Class Object is subclass of another Class Object in Java

我有一个名为“Figure”的抽象父类,我有两个子类“Circle”和“Rectangle”,它们都扩展了这个抽象父类。我试图确定一个图形对象是圆形还是矩形类型。

我原来的代码是:

 public boolean isInstanceOfRectangle(Figure figure)
 {
     boolean isInstance = figure instanceof Rectangle;
     System.out.println("instance of rectangle!");

     return isInstance;
  }

在研究了上面的链接问题后,我重写了我的代码如下:

public boolean isRectangle()
{
    boolean isInstance = Figure.class.isAssignableFrom(Rectangle); 
    System.out.println("instance of rectangle!");
    return isInstance;  
 }

由于某种原因,除非我在主类中包含以下内容,否则这不起作用:

public Class<?> Rectangle;
public Class<?> Circle1;

我不确定将它包含在我的课程中的意义,如果我不这样做,似乎需要我将它作为参数包含在我的方法中。我无法正确调用和测试此方法,因为我不确定在调用时将什么参数传递给该方法。我想写一些类似的东西:

public void mouseReleased(MouseEvent e)
{
    if ((isRectangle(shape1)))
    addRectangle((Rectangle)shape1, e.getComponent().getForeground());

    else if ((isCircle(shape1)))
    addCircle((Circle) shape1, e.getComponent().getForeground());   
 }

其中“shape1”是一个被实例化为圆形或矩形的 Figure 对象。因为参数是 Figure 类型,我不确定如何定义“isRectangle”方法来获取 Figure 对象(抽象父对象)并具体确定它是哪个子类的实例。或者最好不带参数,只通过使用 Figure 对象调用方法来完成工作。我有点困惑如何进行。

*编辑:根据用户的建议,我重写了以下 ,这似乎不起作用,因为在这两种情况下,输出都是 FALSE。

Figure circleObj = new Circle(Color.BLUE);

System.out.println(isInstanceOfRectangle(circleObj));
System.out.println(isInstanceOfCircle(circleObj));

public static boolean isInstanceOfRectangle(Figure figure)
{
    boolean isInstance = figure instanceof Rectangle;
    if (isInstance == true)
        System.out.println("instance of rectangle!");
    else
        System.out.println("is NOT a rectangle");
    return isInstance;
}


public static boolean isInstanceOfCircle(Figure figure)
{
    boolean isInstance = figure instanceof Circle;
    if (isInstance == true)
        System.out.println("instance of circle!");
    else
        System.out.println("is NOT a circle");
    return isInstance;
}

【问题讨论】:

  • 你应该几乎总是重组你的代码以避免需要这样做。
  • 这两种情况都是错误的,因为您在这两种方法中都检查了figure instanceof Rectangle。您应该在第二个中检查figure instanceof Circle
  • 正如@chrylis 提到的,您应该以这样的方式重组代码,以便您可以避免此类检查。一种选择是在 Figure 中创建一个抽象方法并在您的 Circle/Rectangle 类中覆盖它以执行您想要的行为。

标签: java object inheritance instance abstract-class


【解决方案1】:

这将始终返回 false,因为 Figure Class 实例不是 Rectangle Class 实例的子类:

boolean isInstance = Figure.class.isAssignableFrom(Rectangle.class); 

您通常希望在不知道运行时类型的变量的类上调用 isAssignableFrom()
这会更有意义:

Figure figure = ...;
boolean isInstance = Rectangle.class.isAssignableFrom(figure.getClass()); 

这允许知道figure 变量的类的实例IS 是否为Rectangle

引入一种方法来处理需求会更有意义,因为它是动态的,它还允许处理不同的类兼容性检查:

  public static boolean isInstanceOf(Figure figure, Class<?> clazz){
    boolean isInstance = clazz.isAssignableFrom(figure.getClass());
    return isInstance;
  }

你可以这样使用它:

System.out.println(isInstanceOf(new Rectangle(), Rectangle.class));    
System.out.println(isInstanceOf(new Circle(), Rectangle.class));    
System.out.println(isInstanceOf(new Figure(), Rectangle.class));    

打印出来的:

是的

当然,所有这些都会将true 输出为FigureCircleRectangleFigures:

System.out.println(isInstanceOf(new Rectangle(), Figure.class));    
System.out.println(isInstanceOf(new Circle(), Figure.class));    
System.out.println(isInstanceOf(new Figure(), Figure.class));    

【讨论】:

  • 另外,如果你知道你正在检查的课程isAssignableFrom,写figure instanceof Rectangle可能会更容易。
【解决方案2】:

可以使用 .getClas() 方法查找子类

    Rectangle aRectangle = new Rectangle();
    if (aRectangle.getClass == Rectangle.class){
        // Do what you would do if it was a rectangle
        System.out.println("you have a rectangle");
    }   
    else{
        // The figure is not a rectangle 
        System.out.println("the figure is not a rectangle");
    }

【讨论】:

    【解决方案3】:

    我认为没有太多理由让您的代码使用可赋值来复杂化。您的原始代码有效。不仅如此,检查变量的类不是一个好习惯,尝试重构你的代码。 (检查多态性、Barbara Liskov 原理和接口隔离原理) 为了澄清一些事情:图形不是一个对象,因为它是抽象的,它是类型。类型位于变量声明的左侧。

    【讨论】:

      【解决方案4】:

      在我们使用 Java 进行模式匹配之前,您的原始实现是正确且最简单的。

      更详细的解释:

      instanceof 运算符可用于检查对象是否是特定类的实例。这符合您的意图。

      您可以使用ClassA.isAssignableFrom(ClassB) 实现类似的功能。在这里,ClassA 是超类,ClassB 是子类。请注意,此函数比较两个类(Class&lt;?&gt; 的实例),而不是一个实例与一个类。

      您可以使用getClass 方法从实例中获取类,因此,生成的代码将如下所示:

      Rectange.class.isAssignableFrom(figure.getClass())
      

      您提议的支票

      Figure.class.isAssignableFrom(Rectangle);
      

      有多个问题:

      • 语法错误:您需要在右侧有一个 Class&lt;?&gt; 实例,您可以使用类文字 Rectangle.class,但这检查了一个微不足道的事实,并且始终是正确的。
      • 为了修复这个错误,你定义了一个变量Class&lt;?&gt; Rectangle,但是这个变量与Rectangle类没有任何关系,除非用类文字Rectangle.class显式初始化
      • 你不要在任何地方使用图形实例

      【讨论】:

      • 我听说原始实现有效,但是当我尝试实例化一个圆形对象时,圆形和矩形类型都为假
      • 您在 isInstanceOfCircle 方法中再次测试 Rectangle
      【解决方案5】:

      我将在这里插话并指出这些方法中的错误:

      
      public static boolean isInstanceOfRectangle(Figure figure)
      {
          //boolean isInstance = figure instanceof Rectangle;
          boolean isInstance = figure instanceof Rectangle;
          if (isInstance == true)
              System.out.println("instance of rectangle!");
          else
              System.out.println("is NOT a rectangle");
          return isInstance;
      }
      
      
      public static boolean isInstanceOfCircle(Figure figure)
      {
          //boolean isInstance = figure instanceof Rectangle;
          boolean isInstance = figure instanceof Rectangle;
          if (isInstance == true)
              System.out.println("instance of circle!");
          else
              System.out.println("is NOT a circle");
          return isInstance;
      }
      

      在第二种方法中,你想要的行为是让它检查它是否是一个圆。但是,您检查它是否是一个矩形。

      你应该检查figure instanceof Circle而不是figure instanceof Rectangle

      PS。可以使用instanceof。其他任何东西都是大材小用。

      【讨论】:

        猜你喜欢
        • 2015-08-03
        • 2016-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-26
        • 1970-01-01
        相关资源
        最近更新 更多