Java继承分析
Posted 無昂博奥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java继承分析相关的知识,希望对你有一定的参考价值。
本文章观点结合《Java编程思想》、《设计模式之禅》、《大话设计模式》整理而成。站在巨人的肩旁上才能让我们看的更远。
继承
继承是Java编程中重要的一个特性,使用继承可以提高代码的重用性。文字总是显得过于苍白,下面是继承的关系图。
关系图
优点
-
提高代码的重用性,减少创建类的成本,当创建一个类之后,如果有一个类与其具有相似的功能,那么就不需要再创建一个新类。
-
子类可以形似基类,但又和基类不同。有两种方式可以使子类和基类产生差异:
1、第一种是直接在子类中添加新方法,当基类不能满足我们需求的时候,我们可以使用此方式来解决;2、第二种是改变现有基类的方法的行为,也就是Java中的覆盖。
例如我们android中自定义View中OnDraw()函数,TextView和ImageView虽然都继承了View,但分别在OnDraw()函数中做了不同的行为;
-
提高代码的可扩展性。
缺点
- 继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;
- 增强了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改。
里氏替换原则
之所以把这个原则放到继承里面说明,是因为里氏替换原则的核心原理是抽象。而抽象又依赖于继承这个特性。可以说里氏替换原则是对良好的继承定义了一个规范。
定义
所有引用基类的地方必须能透明地使用其子类的对象。这句话的意思是说在基类出现的地方子类就可以出现,而且替换为子类也不会有任何异常。但是反过来就不行了,有子类出现的地方,父类未必就合适出现。
目的
构建扩展性更好的系统,里氏替换原则和开闭原则往往是生死相依、不离不弃的,通过里氏替换原则来达到对扩展开放,对修改关闭的效果。
举例
Android中Window和View的关系来说。
//窗口类
public class Window
public void show(View child)
child.draw();
//建立抽象View,测量视图的宽高为公用代码,绘制实现交给具体的子类
public abstract class View()
public abstract void draw();
public void measure(int width,int height)
//测量视图大小
//文本控件类的实现
public class TextView extends View
public void draw()
//绘制文本
//图片控件类的实现
public class ImageView extends View
public void draw()
//绘制图片
通过在window类的show函数中传入泛化的View。
向上转型
在Window
类的show函数参数是View基类,使用的过程中,此时如果想要显示一个TextView
的话,使用方式如下:
Window w = new Window();
w.show(new TextView);
上面这段代码在show函数中,将TextView看做是View的一种,把子类看做是它的基类的这个过程称为向上转型。
向下转型
我们在使用容器存储对象的时候,因为容器只存储Object
类型,所以当将对象引用置入容器时,它必须被向上转型为Object
。当取回的时候,就获得了一个对Object
对象的引用,而不是存储时的那个类型的对象的引用。那么,怎样才能将它变回存储时的那个对象呢?这里就用到了向下转型,即将上层一个更泛化的类型,向下转型为一个更具体的类型。
向下转型是不安全的,例如上面的代码,TextView是一种View类型,但是不知道某个View是TextView还是ImageView所以除非确切知道所要处理的对象的类型,否则向下转型时就有可能出现ClassCastException
。
总结
在开发过程中,使用继承可以大大提高我们开发的效率,在代码设计的过程中,也尽可能的去使用继承这一特性。当然凡事不是绝对,事物总有两面性,如何权衡利弊还需要根据我们的具体情况来做选择,掌握设计模式和编程思想,不一定会让我们变得更好,但至少不会把我们得更差。
以上是关于Java继承分析的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript中使用new操作符实例化对象时构造函数有返回值的情况分析
JavaScript中使用new操作符实例化对象时构造函数有返回值的情况分析