里氏代换原则
一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类和子类对象的区别。也就是说,在软件里面,把父类替换成它的子类,程序的行为没有变化。一个软件实体如果使用的是一个子类的话,那
么它不能适用于其父类。
一、里氏代换原则例子
1.1 Person
public class Person {
public void display(){
System.out.println("this is person");
}
}
1.2 Man
public class Man extends Person {
public void display(){
System.out.println("this is man");
}
}
1.3 MainClass
如果使用一个父类,一定适合其子类
public class MainClass {
public static void main(String[] args){
//如果使用一个父类,一定适合其子类
Person person = new Person();
display(person);
Person man = new Man();
display(man);
}
public static void display(Person person){
person.display();
}
}
1.4 MainClass
如果使用一个子类,不能适合其父类
public class MainClass {
public static void main(String[] args){
//如果使用一个父类,一定适合其子类
Person person = new Person();
display(person); //报错
Person man = new Man();
display(man); //报错
}
//修改参数为Man
public static void display(Man man){
man.display();
}
}
二、问题分析:企鹅是一种鸟类吗
2.1 Bird
public interface Bird {
public void fly();
}
2.2 LaoYing
public class LaoYing implements Bird {
public void fly() {
System.out.println("老鹰在飞");
}
}
2.3 MaQue
public class MaQue implements Bird {
public void fly() {
System.out.println("麻雀在飞");
}
}
2.4 QiE
//企鹅不能飞,但是鸟类,被强制实现了接口,飞的方法就必须实现,这时候就不符合里氏代换原则
//所以企鹅不应该实现该接口
public class QiE {
}
2.5 MainClass
public class MainClass {
public static void main(String[] args){
fly(new LaoYing());
fly(new QiE()); //报错,因为企鹅是鸟类,但是不能飞,不应该实现该接口
}
public static void fly(Bird bird){
bird.fly();
}
}
三、问题分析:正方形是一种长方形吗
现实生活中认为,正方形是一种特殊的长方形,但该例子中,我们把长方形跟正方形看成两个独立的类,长方形里面有width、height两个属性,正方形里面有side一个属性,所以正方形不是长方形的子类,不存在里氏代换关系。
如果我们让正方形继承长方形,并覆盖长方形的getWidth、getHeight等方法,设置和返回的都是side
3.1 CFX
public class CFX {
private long width;
private long height;
public long getWidth() {
return width;
}
public void setWidth(long width) {
this.width = width;
}
public long getHeight() {
return height;
}
public void setHeight(long height) {
this.height = height;
}
}
3.2 ZFX
public class ZFX extends CFX {
private long side;
public long getWidth() {
return this.getSide();
}
public void setWidth(long width) {
this.setSide(width);
}
public long getHeight() {
return this.getSide();
}
@Override
public void setHeight(long height) {
this.setSide(height);
}
public long getSide() {
return side;
}
public void setSide(long side) {
this.side = side;
}
}
3.3 MainClass
在方法test中,打印出高和宽,编译器可以通过,正方形跟长方形都可以使用这个方法,但在resize方法中,对于正方形是死循环,这时候便不符合一定适合子类这个规则
public class MainClass {
public static void main(String[] args){
//编译器通过,可以使用
CFX cfx = new CFX();
cfx.setHeight(10);
cfx.setWidth(20);
test(cfx);
resize(cfx);
CFX zfx = new ZFX();
zfx.setWidth(20);
test(zfx);
//程序一直执行
resize(zfx);
}
public static void test(CFX cfx){
System.out.println("高:"+cfx.getHeight());
System.out.println("宽:"+cfx.getWidth());
}
//当长方形的宽高小于等于高的时候,宽就会递增
//对于正方形就是死循坏
//这时候便不符合适合子类这个规则
public static void resize(CFX cfx){
while(cfx.getHeight()<=cfx.getWidth()){
cfx.setHeight(cfx.getHeight()+1);
test(cfx);
}
}
}