Reputation: 3
I'm having some trouble understanding how OOP, Abstract Classes and lists. My current project is in Processing - Just for prototyping of course.
My problem is that I've a list of objects with some of the same variables. So I created an abstract class for them and then a list of all the objects (Abstract class as list) and then added the variant objects to the "abstract" list.
Here is the code - The whole deal can be found just beneath:
ArrayList<Vehicle> vehicles = new ArrayList<Vehicle>();
void setup() {
vehicles.add(new Motorcycle());
vehicles.add(new Motorcycle(2,"Yamaha"));
vehicles.add(new Truck());
vehicles.add(new Truck(4,"ASU AC2",2));
print(vehicles);
vehicles.get(3).dropLastTrailer();
}
Truck:
class Truck extends Vehicle {
int numOfTrailers;
Truck() {
super();
numOfTrailers = 0;
}
Truck(int size, String name, int numOfTrailers) {
super(size, name);
this.numOfTrailers = numOfTrailers;
type = "Truck";
}
void dropLastTrailer() {
numOfTrailers--;
println("Dropped one trailer, the truck now got " + numOfTrailers + " trailers");
}
}
Vehicle:
abstract class Vehicle {
int speed, size;
String name;
String type;
Vehicle() {
this((int)random(0,6),"Unknown Vehicle");
type = "Vehicle";
}
Vehicle(int size, String name) {
this.size = size;
this.name = name;
}
String toString() {
return (name + " is " + size + "m long " + type);
}
}
The code works up until I try to call the "dropLastTrailer" function where it says the method doesn't exist. I guess this is properly because it thinks it's just a Vehicle object, and not a Truck.
How can I fix this?
Full Code can be found here: https://github.com/Jalict/processing-experiments/tree/master/oop_abstract_list
Upvotes: 0
Views: 180
Reputation: 15896
Your ArrayList
is type of <Vehicle>
and Vehicle
doesn't have dropLastTrailer()
method.
So First you have to Downcast your object into Truck
then only you can able to call this function like.
((Truck) vehicles.get(3)).dropLastTrailer();
Upvotes: 0
Reputation: 6969
Dumb fix: cast
((Truck)vehicles.get(3)).dropLastTrailer();
but that's kind of dangerous. How do you know whether that element in a list is indeed a truck?
Better:
Vehicle v = vehicles.get(3);
if (v instanceof Truck) {
// then we can safely cast
((Truck)v).dropLastTrailer();
}
Upvotes: 0
Reputation: 1502746
How would you expect the compiler to know that it is a Truck
? You've declared a list of vehicles. Imagine if you were using list.get(0)
instead of list.get(3)
- then the value would be a reference to a Motorcycle
, not a Truck
.
You can fix this by casting:
((Truck) vehicles.get(3)).dropLastTrailer();
... but at that point your code is assuming the type of an object within the list, which isn't ideal. You could make this conditional:
Vehicle mightBeTruck = vehicles.get(3);
if (mightBeTruck instanceof Truck) {
Vehicle truck = (Truck) mightBeTruck;
truck.dropLastTrailer();
}
That's safer, but it's still not great from a design perspective. Unfortunately the sample given doesn't have enough context to apply it to a real world task - sometimes things like this really are necessary. Usually there are cleaner approaches, but it depends on what you're trying to achieve.
Upvotes: 1