第一种定义,也是最正宗的定义:If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.
如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。
第二种定义:Functions that use pointers or references to base classes must be able to useobjects of derived classes without knowing it.
所有引用基类的地方必须能透明地使用其子类的对象。
第二种定义比较通俗,容易理解:只要有父类出现的地方,都可以用子类来替代,而且不会出现任何错误和异常。但是反过来则不行,有子类出现的地方,不能用其父类替代。
举个例子:
如果所示,Client调用CarService方法给车(Car)加油,代码如下:
public class Car {
private String brand;
private String color;
public Car(String brand, String color){
this.brand = brand;
this.color = color;
}
public String getColor() {
return color;
}
public String getBrand() {
return brand;
}
}
public class CarService {
public void supply(Car car){
refuel(car);
}
private void refuel(Car car) {
System.out.println("refueling for "+car.getBrand()+" car ");
}
}
public class ElectricCarService extends CarService {
public void supply(Car car){
charge(car);
}
public void charge(Car car){
System.out.println("charge for car...");
}
}
public class Client extends TestCase {
private List<Car> carList = new ArrayList<Car>();
public void test(){
Car car = new Car("volkswagan","blue");
carList.add(car);
service();
}
private void service() {
CarService supplier = new CarService();
for (Car car : carList) {
supplier.supply(car);
}
}
}
如代码所示,Client调用Service方法给汽车加油。如果这个时候把CarService换成子类ElectricCarService,再调用Service给汽车加油,但是子类没有加油的方法,只有充电的方法,则势必会导致原来父类给汽车加油的行为失败。即子类没办法取代父类,因此违反了里氏替换原则。
解决方法:一般是把补给的行为抽象出来,然后加油和充电作为两个实现类,分别以不同的方式补给。