Implementing subtypes for interface methods Java

Will170393 :

I've been going over Generic classes and methods in Java and came across this question in a past paper

enter image description here

I tried implementing the interface and classes proposed in the question, including the refuel method, and found no problem with passing the Car argument as a parameter

Motorized interface

public interface Motorized {

    public int getFuel();

}

Vehicle class

public abstract class Vehicle{

    private int fuel;

    public Vehicle(int fuel) {

        this.fuel = fuel;
    }

    public String toString(){

        return("Fuel is: " + getFuel());
    }

    public int getFuel() {

        return fuel;
    }
}

Car class

public class Car extends Vehicle implements Motorized {

    int seats;

    public Car(int fuel, int seats) {

        super(fuel);
        this.seats = seats;
    }

    public int getSeats() {

        return seats;
    }

    @Override
    public String toString(){

        return("Fuel is: " + getFuel() + "and the car has" + getSeats() + "seats.");
    }
}

test method

public class VehicleTest {

    public static Motorized refuel(Motorized v) {

        return v;
    }

    public static void main(String[] args) {

        Car car = new Car(15, 5);

        System.out.println(refuel(car));
    }
}

Can somebody explain to me what the problem should be with this question and why my implementation of it doesn't reflect this problem?

Lino :

The problem lies with the return value of the method:

public static Motorized refuel(Motorized v)

You said you had no problems passing in a Car and that is a completly valid statement. But you have not tried to get the value back from the refuel method:

Car car = ...
Car refueled = refuel(car); // compiler error: Motorized is not assignable to Car!

The return type is Motorized although Car extends Motorized, you can't be sure that the Motorized instance that is returned will always be a Car. See this simplified example:

public static Motorized refuel(Motorized v) {
    // try to refuel
    // uh oh... the gas station exploded
    // you have to change to a motorbike which just stands around
    return new Motorbike();
}

Now you maybe expect a Car but you get a Motorbike, so even a cast fails:

Car refueled = (Car) refuel(car); // ClassCastException, Motorbike is not a Car

You can do this with generics though:

public static <M extends Motorized> M refuel(M m) {
    // refuel the motorized vehicle
    return m;
}

Though if the gas station explodes again, then the method has a problem. It doesn't know what M actually is. So this can be a lifesaver for headaches to you.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=97796&siteId=1