I am trying to access methods in the class Car from my arraylist. 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()
The main
method looks like this:
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:
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. 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
. Take your above example, you might want to have a NamedVehicle
with that getID()
method. 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.
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.
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:
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
).
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.
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.
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
).
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.
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>
):
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
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.