OO中的继承性的思考和说明:
- 继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
- 继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子
类的功能都有可能产生故障 - 在编程中,如何正确的使用继承?=>里氏替换原则
基本介绍
里氏替换原则:
- 所有引用基类的地方必须能透明地使用其子类的对象
- 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
- 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖来解决问题。
下面写一段代码,来看下问题:
首先,来建一个A类,你们有一个两个数相减的方法:
// A类
class A {
// 返回两个数的差
public int func1(int num1, int num2) {
return num1 - num2;
}
}
然后建立一个B类去继承A类,并且重写了A类的func1方法,改成两个数相加:
// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends A {
//这里,重写了A类的方法, 可能是无意识
public int func1(int a, int b) {
return a + b;
}
public int func2(int a, int b) {
return func1(a, b) + 9;
}
}
最后main方法调用:
public static void main(String[] args) {
// TODO Auto-generated method stub
A a = new A();
System.out.println("11-3=" + a.func1(11, 3));
System.out.println("1-8=" + a.func1(1, 8));
System.out.println("-----------------------");
B b = new B();
System.out.println("11-3=" + b.func1(11, 3));//这里本意是求出11-3
System.out.println("1-8=" + b.func1(1, 8));// 1-8
System.out.println("11+3+9=" + b.func2(11, 3));
}
后台输出:
这里可以看到,如果直接new一个A类对象出来,然后直接使用func1方法,输出的接口是没问题的。但是当我们new一个b类对象的时候。去使用A类的func1方法的时候,这个时候,结果输出就不对了,因为B类虽然继承了A类,可以使用A类里面的方法,但是你又在B类里面重写了func1。这个时候,输出的结果就是两个数相加了。这其实已经违反了里式替换原则。父类的方法能不重写,尽量不要重写,你想使用A类中的func1方法,但是又在B类中重写了func1方法,那这样,你的继承又有什么意思呢?
我们通过里式替换原则来改一下代码,先建立一个Base类:
//创建一个更加基础的基类
class Base {
//把更加基础的方法和成员写到Base类
}
然后,再建立A类和B类,去分别继承Base类,然后,B类里面,组合A类(不通过继承)。这样A类和B类相互直接就低耦合了:
// A类
class A extends Base {
// 返回两个数的差
public int func1(int num1, int num2) {
return num1 - num2;
}
}
// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends Base {
//如果B需要使用A类的方法,使用组合关系
private A a = new A();
//这里,重写了A类的方法, 可能是无意识
public int func1(int a, int b) {
return a + b;
}
public int func2(int a, int b) {
return func1(a, b) + 9;
}
//我们仍然想使用A的方法
public int func3(int a, int b) {
return this.a.func1(a, b);
}
}
这样子的话,A类的方法和B类的方法相互之间,就变的很透明了,之间不相干。这也是里式替换原则的核心所在。能尽量用聚合,组合的尽量用,少使用继承。