[英]Java: Accessing subclass methods from objects in arraylist
我正在尝试从我的arraylist访问Car类中的方法。 类层次结构本质上是:
class Vehicle {}
class Car extends Vehicle {}
class Chevy extends Car {}
class Ford extends Car {}
在此示例中, Car
类具有名为getID()
的吸气剂
main
方法如下:
Ford vehicle1 = new Ford(id, model, etc);
Chevy vehicle2 = new Chevy(id, model, etc);
ArrayList<Vehicle> list = new ArrayList<Vehicle>();
list.add(vehicle1);
list.add(vehicle2);
通过大量的试验,我能够像这样访问错误getID()方法:
System.out.println("Vehicle ID: " + ((Chevy) list.get(1)).getID());
哪个可行...我简直无法想象自己正在以正确的方式进行操作。 有没有更好的方法来访问这些子类方法?
对于严肃的程序,您的Vechicle
接口应定义所有车辆通用的所有行为方法,其中应包括getID()
方法。 但是,在某些情况下,您可能希望有一种仅适用于特定类型车辆的特定方法。 那么您需要在Vehicle
子类或子接口中执行此操作。 以上面的示例为例,您可能希望拥有一个带有该getID()
方法的NamedVehicle
。 如何安排接口和类取决于您。 如果有帮助,请参考网桥设计模式。
综上所述,您确实希望在非常偶然的地方进行显式转换。
在列表中添加子类对象看起来不错,但是当您遍历列表时,您将永远不知道将访问哪个子对象。
我建议您可以通过以下方式使父对象指向子对象。
Car vehicle1 = new Ford(id, model, etc);
Car vehicle2 = new Chevy(id, model, etc);
然后添加到列表中,如图所示。 当您遍历列表时,您将根据instanceof check将其向下转换,这将使其更加传统。
例如:
Car c = (Car)list.get(0)).getID();
if(c instanceof Ford){
Ford f = (Ford)c;
System.out.println(f.getId());
}
为什么车辆不是接口(类无法扩展接口,而是实现了接口)?
据我了解,而Car
却没有Vehicle
的getId()
,这就是为什么不将Vehicle
数组列表对象转换为具有此类方法(如Chevy
)的子类会导致错误的原因。
如果您这样做:
System.out.println("Vehicle ID: " + ((Car) list.get(1)).getID());
它会工作的。
我建议您将Vehicle
为界面:
interface Vehicle{
public int getId();
}
class Car implements Vehicle{ //altough I think this also should be abstract
int id;
@Override
public int getId(){
return id;
}
}
使用此配置,您可以执行以下操作:
Car vehicle1 = new Ford(id, model, etc);
Car vehicle2 = new Chevy(id, model, etc);
ArrayList<Vehicle> list = new ArrayList<Vehicle>();
list.add(vehicle1);
list.add(vehicle2);
System.out.println("Vehicle ID: " + list.get(1).getID()); //Chevy ID
由于getId()
方法是在Car
类中声明的,因此您只能通过继承来访问此方法( 当然,需要用protected
或public
修饰符标记 )。
因此, Car
任何子类都可以访问getId()
方法,并且应该具有在Car#getId
标记的行为,除非该方法在相关子类型中被覆盖 ,因此在运行时将根据当前对象类型和方法来评估方法的行为。不是对象引用。
现在介绍最著名的OO(面向对象)功能之一,即多态 (许多形式),它使您可以传递需要Car
任何Car
子类型,并在需要Car
实例时返回任何Car
子类型。
因此,要sumup,你能有什么Car
亚型在ArrayList
的Car
(S): Ford
, Chevy
,你就能再调用任何Car
上的列表中的任何项目实例方法(这是什么真正的类型,它不无关紧要,因为它是Car
的孩子)。
现在的主要问题是,所描述的行为不能在另一侧进行,因此,除非在``''下满足显式强制转换,否则父引用 (在您的情况下为Vehicle
)将永远不会知道其后代的行为(在您的情况下为Car
)。路。
然后,您只需要简单地使用Car
作为泛型类型来实例化ArrayList
(这就是您说<Vehicle>
, <Car>
时所做的事情):
public static void main(String[] args)
{
Ford vehicle1 = new Ford(id, model, etc);
Chevy vehicle2 = new Chevy(id, model, etc);
ArrayList<Car> list = new ArrayList<Car>(); //Use a Car as generic type so you can call all car methods
list.add(vehicle1);
list.add(vehicle2);
for(Car car : list)
{
System.out.println(car.getId()); // Iterate over the list and retrieve each element ID
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.