设计模式-里氏替换原则

设计模式-里氏替换原则

优点

面向对象的语言继承必不可少的,有如下优点

  1. 代码共享,减少创建类的工作量
  2. 提高代码的重用性
  3. 提高代码的可扩展性
  4. 提高代码的可扩展性
  5. 提高产品代码的开放性
  6. 继承侵入性 只要继承,必须拥有父类的内容
  7. 降低代码的灵活性,子类必须拥有父类的属性和方法
  8. 增强耦合性。

提供规范

里氏替换原则,为继承定义规范。

长方形是不是正方形

正方形是一种特殊的长方形,如果将正方形设计为长方形的子类,不符合里氏替换原则

下方有三个类

类图如下

关系如上所示

package demo1;

public class SmartTest {
	/*
	 * 长方形的长增加超过宽
	 * 
	 * @param r
	 * */
	
	public void resize(Rectangle r) {
		while (r.getHeight() <= r.getWidth()) {
			r.setHeight(r.getHeight() + 1);
		}
	}
}
package demo1;
/*
 * 定义一个长方形类
 * @author ming
 * */

public class Rectangle {
	protected long width;	// 可以访问基类继承而来的,不能访问基类本身的,对同包内的可见,并且子类也可见
	protected long height;
	
	public void setWidth(long width) {
		this.width = width;
	}
	
	public long getWidth() {
		return this.width;
	}
	
	public void setHeight(long height) {
		this.height = height;
	}
	
	public long getHeight() {
		return this.height;
	}
}
package demo1;
/*
 * 定义一个正方形类继承自长方形类
 * 
 * @author ming
 * 
 * */
public class Square extends Rectangle{
	public void setWidth(long width, long height) {
		this.width = width;
		this.height = height;
	}
	
	public long getWidth() {
		return width;
	}
	
	public void setHeight(long height, long width) {
		this.height = height;
		this.width = width;
	}
	
	public long getHeight() {
		return height;
	}
}

在上面的三块代码中,当调用SmartTest类的resize方法的时候,如果传入的是父类,那么将会可以的,如果传入的是子类,正方形,那么将会不可以的。

即。上方的为长方形行,正方形不行。

所以上面的栗子不符合里氏替换原则。

解决方法,使用继承时,要遵守里氏替换原则,类B继承类A时,不要重写父类A的方法,也不能重载父类A的方法。

如果代码更改如下更改

让其两个都共同定义同一个父类即可

其中最上层的类为两个类的抽象类。

改进如下

package com.ming;

/*
 * 定义一个四边形类,只有get方法set方法
 * @author ming
 * */
public abstract class Quadrangle {
	protected abstract long getWidth();
	protected abstract long getHeight();
}
package com.ming;

public class Rectangle extends Quadrangle {
	private long width;
	private long height;
	
	public void setWidth(long width) {
		this.width = width;
	}
	
	public long getWidth() {
		return this.width;
	}
	
	public void setHeight(long height) {
		this.height = height;
	}
	
	public long getHeight() {
		return this.height;
	}
}
package com.ming;

public class Square extends Quadrangle{
	private long width;
	private long height;
	
	public void setWidth(long width) {
		this.height = width;
		this.width = width;
	}
	
	public long getWidth() {
		return this.,width;
	}
	
	public void setHeight(long height) {
		this.height = height;
		this.width = height;
	}
	
	public long getHeight() {
		return this.height;
	}
}

在上方的图中,由于两个为平级关系,所以父类的地方,换成子类也都可以。

总结

里氏替换原则;父类可以的地方,换成子类也同样可以。

为什么要符合

一个栗子

package com.ming2;

public class A {
	public int func1(int a, int b) {
		return a-b;
	}
}
package com.ming2;

public class B extends A{
	public int func1(int a, int b) {
		return a+b;
	}
	
	public int func2(int a, int b) {
		return func1(a,b)+100;	// 调用func1
	}
}

在上方中,如果这样书写

package com.ming2;

public class Client {
	public static void main(String[] args) {
		B b = new B();
		System.out.println(b.func1(100, 50));
	}
}

就违反了里氏替换原则,即子类能使用的时候,父类也必须能使用。

www.iming.info

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT笔记

2016头条校招笔试题(LRU)算法之JAVA实现

操作系统中可以使用LRU(Least Recently Used)内存淘汰旧数据的策略,如果内存需要加载新数据但空间不足,则会按照最近访问时间进行排序,并将最老...

358100
来自专栏向治洪

Kotlin之Elvis 操作符

Elvis 操作符的优先级 首先要注意到,Elvis 操作符的优先级是比较低的,特别是比加减乘除的运算符低,混合运算时一定要记得加上括号。比如: fun <T>...

25750
来自专栏数据结构与算法

3339: Rmq Problem

Description image.png Input image.png Output image.png Sample Input 7 5 ...

357110
来自专栏JAVA同学会

利用java反射机制编写solr通用的java客户端

通过上一篇的讲解,我们知道了dynamicFiled字段,它是动态的,不需要显示的声明。而且一些常用的基本类型solr已经默认给我们创建好了。

20210
来自专栏一直在跳坑然后爬坑

前往kotlin的路上

官网:http://kotlinlang.org/docs/reference/ github:https://github.com/JetBrains/ko...

10910
来自专栏javathings

为什么重写 equals 时必须重写 hashcode?

equals 默认是和==一样,判断引用是否相等的,一般需要覆写后才能实现真正的判等。

1.3K20
来自专栏芋道源码1024

一个简单案例,5 分钟看懂 Java Lamdba 表达式

JDK8引入了一个新玩意,叫做lamdba(那么大)的表达式,说得神乎其神,说真的,这玩意吧,并不难,但是要讲清楚吧,也不是太容易的事情。

26730
来自专栏Python小屋

对Python列表进行封装和二次开发实现自定义栈结构

设计自定义栈类,模拟入栈、出栈、判断栈是否为空、是否已满以及改变栈大小等操作。 class Stack: #构造方法 def __init__(self, ...

32570
来自专栏温安适的blog

JDK1.8下关于MethodHandle问题

44980
来自专栏海天一树

小朋友学C++(4):public, protected, private

面向对象有三大特征:封装、继承、多态。(具体会在之后的课程里讲) C++用三个关键词来表示访问范围:public, protected, private。 pu...

26860

扫码关注云+社区

领取腾讯云代金券