It
is possible to extend an existing interface. The purpose behind doing so is to
add more declarations, both constants and methods, to an existing interface.
This helps in not breaking the existing applications that have implemented the
earlier interface. We will now extend our MileageEfficiency interface from the
previous post to provide a new way to compute the fuel efficiency of the newly
introduced hybrid cars on the market that use both gasoline and electric
batteries.
We define this new interface as follows:
interface ExtendedMileageEfficiency extends MileageEfficiency {
public float getFuelEfficiency();
public float getElectricEfficiency();
}
To extend an existing interface, we use the keyword extends, just the way we did for extending class definitions. The interface declares two new methods: one for computing the fuel efficiency of the car and the other one for the battery consumption. The getMilesPerGallon method of the base interface will have an altogether different implementation that uses these two efficiencies to return a newly computed efficiency to the user. The declaration of the HybridVehicle class that implements this interface and the test program that creates an instance of this hybrid car are given in here.
interface MileageEfficiency {
public float getMilesPerGallon();
}
interface ExtendedMileageEfficiency extends MileageEfficiency {
public float getFuelEfficiency();
public float getElectricEfficiency();
}
class GasVehicle implements MileageEfficiency {
private float fuelConsumed;
private float tripCounter;
public float getMilesPerGallon() {
return tripCounter / fuelConsumed;
}
public void makeTrip() {
tripCounter = 100;
fuelConsumed = 8.5f;
}
}
class ElectricVehicle implements MileageEfficiency {
private float kwPowerConsumed;
private float tripCounter;
public float getMilesPerGallon() {
return tripCounter / kwPowerConsumed;
}
public void makeTrip() {
tripCounter = 100;
kwPowerConsumed = 5.6f;
}
}
class HybridVehicle implements ExtendedMileageEfficiency {
private float tripCounter;
private float fuelConsumed;
private float kwPowerConsumed;
public float getFuelEfficiency() {
return tripCounter / fuelConsumed;
}
public float getElectricEfficiency() {
return tripCounter / kwPowerConsumed;
}
public float getMilesPerGallon() {
return 0.8f * getFuelEfficiency() + 1.12f % getElectricEfficiency();
}
public void makeTrip() {
tripCounter = 100;
fuelConsumed = 4.1f;
kwPowerConsumed = 3.4f;
}
}
public class EnhancedTestDrive {
public static void main(String[] args) {
GasVehicle gasolineVehicle = new GasVehicle();
gasolineVehicle.makeTrip();
System.out.printf("Efficiency of Gas Vehicle (miles/gallon): %.02f%n", gasolineVehicle.getMilesPerGallon());
ElectricVehicle electricVehicle = new ElectricVehicle(); electricVehicle.makeTrip();
System.out.printf("Efficiency of Electric Vehicle (miles/kw): %.02f%n", electricVehicle.getMilesPerGallon());
HybridVehicle hybridVehicle = new HybridVehicle();
hybridVehicle.makeTrip();
System.out.printf("Efficiency of hybrid Vehicle "
+ "(miles/EnergyConsumed): %.02f%n",
hybridVehicle.getMilesPerGallon());
}
}
By this time, we have certainly started realizing (and appreciating) the use of interfaces. The interface we initially created provided a standard notation to the developer to compute the fuel efficiency of different types of cars. Later on, when the technology has been enhanced and new types of cars are introduced on the market, we could extend our existing interface and yet retain the same interface method getMilesPerGallon to compute the efficiency of the new cars. For a developer, the consistent interface he sees while writing an application is the greatest advantage to using interfaces.
Sushant Mishra
31-Mar-2017