【问题标题】:Does a SubClass object in an ArrayList<SuperClass> keep methods unique to SubClass?ArrayList<SuperClass> 中的子类对象是否保留子类独有的方法?
【发布时间】:2013-11-30 02:02:52
【问题描述】:

基本上是标题所说的,但有些详细说明。我有一个带有几个子类的超类。我需要一个 ArrayList 来保存这两种类型的子类,因此是 SuperClass 类型的 ArrayList。我尝试使用ArrayList.get(0).getQuantity(); 访问Subclass1 的getQuantity() 方法(假设索引0 属于SubClass1 类型)。我收到错误:未定义类型 SuperClass 的 getQuantity。

SubClass 对象放入 SuperClass ArrayList 时是否不保留其属性?如果他们确实保留了他们的属性,我该如何访问它们?

【问题讨论】:

  • 最初这听起来像是重复,但经过大约 20 分钟的研究,一些帖子触及了同一主题,但并没有完全回答我的问题。

标签: java inheritance arraylist


【解决方案1】:

对象本身仍然是subclass,但是当您将它们从集合中取出时,它只知道superclass,因此它无法告诉您哪个是哪个,它必须选择共同点。

如果您确切知道特定索引包含Subclass 类型的对象,您可以直接转换它:

Subclass myObject = (Subclass) list.get(0);
System.out.println(myObject.getQuantity());

它应该可以工作。

更安全的方法是测试对象是否真的如您所想:

SuperClass myObject = list.get(0);
if ( myObject instanceof Subclass) {
  Subclass mySubObject = (Subclass) myObject;
  System.out.println(mySubObject.getQuantity());
}

如果对象不是Subclass 类型,则第一个示例引发异常,第二个示例不会,因为它之前进行了测试以确保。

这里需要了解的是SuperClass myObject = list.get(0)不是对象本身,而是访问内存中对象的引用。将其视为允许您控制对象的遥控器,在这种情况下,它不是功能齐全的遥控器,因为它不会显示您的所有对象可以做什么,因此您可以切换到更好的遥控器(如@ 987654329@) 以访问所有功能。

我肯定会推荐Head First Java book,因为它非常详细地介绍了这些内容(我从那里偷了这个远程示例)。

【讨论】:

  • 好答案。我想知道将来甲骨文是否会解决这个问题,或者干脆放弃它。哎呀,这可能是某种用途,但我想不出。
  • 这不是问题,这就是面向对象语言(和泛型)的工作方式,你不能说你的列表只包含Subclass,因为它不包含并且编译器 强制执行。
  • 我将在本学期之后购买 Head First Design Patterns :) 另外,我想知道他们是否会添加一些自动切换“远程”的东西,而不必说我是切换“遥控器”。我认为它可能很有用。
  • 他们可能会在语言中构建一个模式匹配器来帮助解决这个问题,避免丑陋的instanceof 序列,但这通常是设计糟糕的标志(正如@chrylis 其他解决方案指出的那样)而且你应该尽量避免这种风格。
【解决方案2】:

所有对象都保留自己的类标识,但使用ArrayList 的代码并没有直接意识到这一点。就它而言,ArrayList 只保存对SuperClass 类型对象的引用,并且它只能在从它检索的对象上调用SuperClass 的方法。

调用代码可以使用instanceof或类似的技术来确定集合中的特定对象是否属于子类型,但这通常是不好的做法,因为它通常表明混合了不同的抽象层次。通常认为这是合理的一种情况是,如果子类具有调用者可以利用的一些可选的高性能特征(并且该测量已确定值得使代码复杂化);一个例子可能是,虽然Listget() 方法没有性能保证,但某些实现,如ArrayList,也实现了RandomAccess,这表明以任何顺序使用get() 都没有性能损失.

【讨论】:

  • 我所看到的是没有太多其他方法,除非您对其进行重组以使 ArrayList 不包含两种类型的子类?
  • @comscis 是的,但这通常是正确的做法。如果您关心SubClass1SubClass2 之间的区别,通常不应将它们放在一个集合中,而应将它们放在不同的集合中。
  • 好消息要知道。出于我的目的,虽然我需要它们在同一个 ArrayList 中。一个子类是费用,另一个是收入。我想按照添加的顺序跟踪它们。将它们分开会增加很多复杂性,所以这次我会偷工减料;)但我可以看到它可能在哪里出现问题。
  • @comscis 根据您要在IncomeExpense 上具体调用的方法,正确的方法可能是在Entry 上添加abstract 方法,即带有@ 的代码987654337@可以来电。这样它就知道它可以调用“任何子类的正确方法”,而不必知道特定对象是哪个子类。
  • 有趣的想法。我会在下一个项目中记住这一点!
【解决方案3】:

当你有一些 ArrayList 并用扩展 SuperClass 的东西填充它时,你必须检查 instanceof 并强制转换以获取特定于这些子类的方法。

例子:

ArrayList<Animal> animals = new ArrayList<Animal>;
animals.add(new Duck());
animals.add(new Cow());
animals.add(new Horse());

for (Animal animal : animals) 
   if (animal instanceof Horse) {
      Horse horse = (Horse)animal;
      horse.gallop();
   }

【讨论】:

    猜你喜欢
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 2015-06-09
    相关资源
    最近更新 更多