【问题标题】:How to identify which type of inherited class the object is? JAVA如何识别对象是哪种类型的继承类? JAVA
【发布时间】:2021-09-19 02:41:31
【问题描述】:

假设我有一个包含 5 个类的 java 代码:

class a = superclass.
class b = class that inherits a methods and have others.'''
class c = class that inherits a methods and have others.'''
class d = class that have an array (lets call "arrayA") of class a objects and other methods(like addObjectToArray).
class e = main.

我的疑惑是:

  1. 有没有办法将 B 或 C 对象添加到 arrayA 以维护此类(B 或 C)的所有不同变量和方法?
  2. 如果我想在主代码中将 B 对象添加到 arrayA(调用 addObjectToArray),然后在主代码的某些部分中识别对象是哪个类(如果是 a、b 或 c),甚至在 d 类中识别它(假设我已初始化并且一切正常。我现在只是在操作数组)我该怎么做?
  3. 有没有办法在arrayA上调用只存在于b类或c类中的方法?怎么样?

如果我不够清楚,我会稍后发布代码。但我也要求提供一些参考来研究对象数组和继承一起操作。

【问题讨论】:

  • "class c = 继承 c 方法的类"
  • 是的。它应该是继承方法的类。我会纠正的。
  • 一个最小且可重现的代码示例比试图用文字表达一切要好,而且 IMO class a {String x;} class b extends a { int y;} 更容易理解。
  • 我建议阅读有关 Liskov 替换原则的内容。这是一种有助于解决这些情况的设计原则。

标签: java class oop


【解决方案1】:

这些都是非常基本的东西,在很多教程中都有介绍,但我会尝试编译一个简短的答案。

首先,让我们把结构弄好。你有这样的东西,不是吗?

class A {
}

class B extends A { 
  void someBMethod();
}

class C extends A{
}

class D {
  A[] arrayA;
}

所以:

有没有办法将 B 或 C 对象添加到 arrayA 来维护这个类(B 或 C)的所有不同变量和方法?

您基本上是在问是否可以将 B 或 C 的实例分配给 D.arrayA?如果是这样,是的,这是可能的,因为两者都扩展了 A 并因此具有“is-a A”属性。它们仍将分别是 B 或 C 实例(就像个别汽车仍然相同,即使它们位于只允许汽车通行的停车场)。

如果我想在主代码中将 B 对象添加到 arrayA(调用 addObjectToArray),然后在主代码的某些部分中确定对象是哪个类(如果是 a、b 或 c),甚至在 d 类中识别它(假设我已初始化并且一切正常。我现在只是在操作数组)我该怎么做?

您是在问如何知道数组元素的类型,对吧?为此使用instanceof,例如:

for(A element : arrayA) {
   if( element instanceof B ) {
     //it's a B
   } else if( element instanceof C ) {
     //it's a C
   }
}

有没有办法在arrayA上调用只存在于b类或c类中的方法?怎么样?

是的,但你需要投射,例如在 if( element instanceof B) 里面你会做这样的事情:

B casted = (B)element;
casted.someBMethod();

一些注意事项

使用instanceof 和强制转换通常不是解决问题的最佳方法,因为这可能很脆弱(尝试将 C 实例强制转换为 B)、乏味(您总是必须先检查类型或思考关于添加E extends A) 等。

所以你最终可能会查到几个原则:

  • 优先组合而不是继承
  • 程序接口
  • 在适当的地方使用泛型

【讨论】:

    【解决方案2】:

    您可以将 B 或 C 实例放在 A[] 数组中,它们保持原样,但是当您从数组中检索它们时,编译器只知道它们为 A 类型,因此调用 B 唯一的成员或 C,您必须在检索对象后将对象转换为 B 或 C。要安全地这样做,您必须先进行instanceof 检查。

    例如:

    for (A item: arrayA) {
        if (item instanceof B) {
            B b = (B)item;
            // do something with b
        }
    }
    

    然而,如果你发现你不得不经常使用instanceof,那么你就有了一个设计问题,你的代码可以通过更好地利用多态性(继承和接口)来简化。 .这不是普遍正确的,但通常是正确的。

    一个常见的新手错误是认为强制转换会将对象从一种类型更改为另一种类型。这是错误的。它只会改变编译器查看对象类型的方式。如果您尝试将对象强制转换为它尚未匹配的类型,您将在运行时收到 ClassCastException(崩溃)。

    【讨论】:

      猜你喜欢
      • 2012-06-25
      • 2018-09-30
      • 2012-07-16
      • 2013-10-16
      • 2013-03-05
      • 2021-02-03
      • 2012-05-18
      • 2012-01-10
      • 2012-01-10
      相关资源
      最近更新 更多