Java 11 Cookbook
上QQ阅读APP看书,第一时间看更新

How to do it...

As an example, we will change the Truck interface. The Car interface can be modified in a similar fashion:

  1. Enhance the Truck interface by adding the getPayloadKg() method, which returns the truck payload in kilograms. You can do this without forcing a change in the TruckImpl class that implements the Truck interfaceby adding a new default method to the Truck interface:
      public interface Truck extends Vehicle {
int getPayloadPounds();
default int getPayloadKg(){
return (int) Math.round(0.454 * getPayloadPounds());
}
}

Notice how the new getPayloadKg() method uses the existing getPayloadPounds() method as if the latter is implemented inside the interface too, although, in fact, it is implemented in a class that implements the Truck interface. The magic happens during runtime when this method becomes dynamically bound to the instance of the class that implements this interface.

We could not make the getPayloadKg() method static because it would not be able to access the non-static getPayloadPounds() method, and we must use the default keyword because only the default or static method of an interface can have a body.

  1. Write the client code that uses the new method:
      public static void main(String... arg) {
Truck truck = FactoryVehicle.buildTruck(3300, 4000, 246);
System.out.println("Payload in pounds: " +
truck.getPayloadPounds());
System.out.println("Payload in kg: " +
truck.getPayloadKg());
}

  1. Run the preceding program and check out the output:
  1. Notice that the new method works even without changing the class that implemented it.
  2. When you decide to improve the implementation of the TruckImpl class, you can do it by adding the corresponding method, for example:
       class TruckImpl extends VehicleImpl implements Truck {
private int payloadPounds;
private TruckImpl(int payloadPounds, int weightPounds,
int horsePower) {
super(weightPounds + payloadPounds, horsePower);
this.payloadPounds = payloadPounds;
}
public int getPayloadPounds(){ return payloadPounds; }
public int getPayloadKg(){ return -2; }
}

We have implemented the getPyloadKg() method as return -2 in order to make it obvious which implementation is used.

  1. Run the same demo program. The results will be as follows:

As you can see, this time, the method implementation in the TruckImpl class was used. It has overridden the default implementation in the Truck interface.

  1. Enhance the Truck interface with the ability to enter the payload in kilograms without changing the implementation of FactoryVehicle and the Truck interface. Also, we do not want to add a setter method. With all of these limitations, our only recourse is to add convertKgToPounds(int kgs) to the Truck interface, and it has to be static since we are going to use it before the object that implements the Truck interface is constructed:
      public interface Truck extends Vehicle {
int getPayloadPounds();
default int getPayloadKg(){
return (int) Math.round(0.454 * getPayloadPounds());
}
static int convertKgToPounds(int kgs){
return (int) Math.round(2.205 * kgs);
}
}