【发布时间】:2012-04-11 07:27:52
【问题描述】:
我有一个问题没有找到答案。 假设我们在 java 或 c# 中有以下代码:
class Car {
/* car stuff */
}
然后在 Java 中
class Truck extends Car {
/* truck stuff */
}
和 C#
class Truck : Car {
/* truck stuff again */
}
在 C# 中,以下工作正常:
List<Car> carList = new List<Car>();
//add some objects to the collection
foreach(Truck t in carList)
//do stuff with only the Truck objects in the carList collection
之所以可行,是因为 Truck 是 Car 的子类,简单来说,这意味着每辆 Truck 也是 Car。但问题是,类型检查已完成,并且仅从 carList 中选择了卡车。
如果我们在 Java 中尝试同样的事情:
List<Car> carList = new ArrayList<Car>();
//add some objects to the collection
for(Truck t : carList)
//**PROBLEM**
由于增强循环内的代码,代码甚至无法编译。相反,我们必须这样做才能获得相同的效果:
for(Car t : carList)
if(t instanceof Car)
//cast t to Truck and do truck stuff with it
这与在 C# 中没有任何问题的想法相同,但在 Java 中您需要额外的代码。甚至语法几乎相同! 它在 Java 中不起作用是有原因的吗?
【问题讨论】:
-
这在 C# 中也不是很干净,因为每辆卡车都是汽车,但不是每辆汽车都是卡车……在 C# 中,转换是在运行时尝试的,但你应该非常小心。 Java 似乎对此更加谨慎,希望程序员先检查一下(当然,如果您知道自己在做什么,C# 版本确实会增加一些好处)。
-
在 C# 中检查每个对象的类型。如果是 Truck,则进入 foreach 循环的主体,否则不进入。这有什么不干净的?我检查它(Java)或运行时检查它(C#)它是相同的最终结果。
-
Java Generics 允许清楚地指定对象,但如果您想要包含任何 Car 的列表,那么您可以编写类似这样的内容。列表 carList = new ArrayList
(); -
@Florian Rappl,大多数程序员不知道他们在做什么,所以我怀疑从长远来看这是一个好处。 Java 设计者有简单的原则尽快找到总线。在这种情况下,运行时可能会发生异常。在 Java 中编译时。
-
只为卡车输入 foreach 循环。例如,如果您在该列表中有总线,则运行时将引发异常。
标签: c# java polymorphism foreach