简体   繁体   English

Java:从arraylist中的对象访问子类方法

[英]Java: Accessing subclass methods from objects in arraylist

I am trying to access methods in the class Car from my arraylist. 我正在尝试从我的arraylist访问Car类中的方法。 The class hierarchy is essentially: 类层次结构本质上是:

class Vehicle {} 
class Car extends Vehicle {} 
class Chevy extends Car {}
class Ford extends Car {}

In this example Car class has a getter called getID() 在此示例中, Car类具有名为getID()的吸气剂

The main method looks like this: 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);

Through a lot of trial an error I've been able to access the getID() method like so: 通过大量的试验,我能够像这样访问错误getID()方法:

System.out.println("Vehicle ID: " + ((Chevy) list.get(1)).getID());

Which works... I just can't imagine I'm doing this the proper way. 哪个可行...我简直无法想象自己正在以正确的方式进行操作。 Is there a better way to access these sub class methods? 有没有更好的方法来访问这些子类方法?

For a serious program, your Vechicle interface should define all the behavioral methods common to all vehicles, which should include your getID() method. 对于严肃的程序,您的Vechicle接口应定义所有车辆通用的所有行为方法,其中应包括getID()方法。 However, in some cases you might want to have specific method that only applies to a certain type of vehicles; 但是,在某些情况下,您可能希望有一种适用于特定类型车辆的特定方法。 then you need to either do that in subclasses or sub interfaces to Vehicle . 那么您需要在Vehicle子类或子接口中执行此操作。 Take your above example, you might want to have a NamedVehicle with that getID() method. 以上面的示例为例,您可能希望拥有一个带有该getID()方法的NamedVehicle How to arrange your interfaces and classes is up to you. 如何安排接口和类取决于您。 Refer to bridge design pattern if that helps. 如果有帮助,请参考网桥设计模式。

Having said the above, in very occasional places you do want to do the explicit cast. 综上所述,您确实希望在非常偶然的地方进行显式转换。

Adding a subclass objects in the list seems fine, but u would never know which child object would be accessed when iterating over the list. 在列表中添加子类对象看起来不错,但是当您遍历列表时,您将永远不知道将访问哪个子对象。

I would suggest you could have parent reference point to child object in the following way. 我建议您可以通过以下方式使父对象指向子对象。

Car vehicle1 = new Ford(id, model, etc);
Car vehicle2 = new Chevy(id, model, etc);

And add then to list as seen. 然后添加到列表中,如图所示。 When you iterate over the list u would downcast it based on the instanceof check, which would make it more conventional. 当您遍历列表时,您将根据instanceof check将其向下转换,这将使其更加传统。

ex: 例如:

Car c = (Car)list.get(0)).getID();
if(c instanceof Ford){

    Ford f = (Ford)c;
    System.out.println(f.getId());

}

Why vehicle isn't an interface (classes cannot extend interfaces, they implement it)? 为什么车辆不是接口(类无法扩展接口,而是实现了接口)?

As far as I understood Vehicle doesn't have a getId() while Car does, that's why not casting your Vehicle array list object to a subclass which has such method (like Chevy ) causes an error. 据我了解,而Car却没有VehiclegetId() ,这就是为什么不将Vehicle数组列表对象转换为具有此类方法(如Chevy )的子类会导致错误的原因。

If you did: 如果您这样做:

System.out.println("Vehicle ID: " + ((Car) list.get(1)).getID());

it would have worked. 它会工作的。

I suggest you to make Vehicle an interface: 我建议您将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;
    }
}

With this configuration you can do: 使用此配置,您可以执行以下操作:

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

Since the getId() method is declared in the Car class, then you can only access this method through inheritance ( of cource need to be marked with either of access modifiers protected or public ). 由于getId()方法是在Car类中声明的,因此您只能通过继承来访问此方法( 当然,需要用protectedpublic修饰符标记 )。

So any subclass of Car will have access to the getId() method and should have the behavior marked in the Car#getId unless that method is overriden in the related subtype thus at runtime the method behavior will be evaluted based on the current object type and not the object reference. 因此, Car任何子类都可以访问getId()方法,并且应该具有在Car#getId标记的行为,除非该方法在相关子类型中被覆盖 ,因此在运行时将根据当前对象类型和方法来评估方法的行为。不是对象引用。

Now coming to one of the most famous OO (Object Oriented) features which is polymorphism (many forms) which let you pass any Car subtype where a car is needed, and return any Car subtype when you expect a Car instance. 现在介绍最著名的OO(面向对象)功能之一,即多态 (许多形式),它使您可以传递需要Car任何Car子类型,并在需要Car实例时返回任何Car子类型。

So to sumup, you can have any Car subtype in an ArrayList of Car (s): Ford , Chevy and you will be able then to call any Car instance method on any item of the list (whatever real type it is, it does not matter since it is a child of Car ). 因此,要sumup,你能有什么Car亚型在ArrayListCar (S): FordChevy ,你就能再调用任何Car上的列表中的任何项目实例方法(这是什么真正的类型,它不无关紧要,因为它是Car的孩子)。

The main issue now is that the described behavior can't go in the other side, so a parent reference (in you case Vehicle ) would never know about its descendants behavior (the Car in your case) unless an explicit cast is met under the road. 现在的主要问题是,所描述的行为不能在另一侧进行,因此,除非在``''下满足显式强制转换,否则父引用 (在您的情况下为Vehicle )将永远不会知道其后代的行为(在您的情况下为Car )。路。

Then you will need simply put, to instantiante your ArrayList using the Car as a Generic type (that's what you are doing when you say <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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM