在面向对象的程序设计语言中,多态是继数据和继承之后的第三张基本特征

多态不但能够改善代码组织结构和可读性,还能够创建可扩展的程序——即无论在项目最初创建时还是在需要添加新功能时都可以"生长"的程序。

封装通过合并特征和行为来创建新的数据类型。"实现隐藏"则通过将细节"私有化",把接口和实现分离开来。多态的作用就是消除类型之间的耦合关系。

多态方法调用允许一种类型表现出与其他相似类型之间的区别。

8.1 再论向上转型

把某个对象的引用视作对其基类的引用称为向上转型——因为再继承树中,基类是放置在上方的。

8.2 转机

基类如何知道引用指向哪个导出类?

8.2.1 方法调用绑定

将一个方法调用同一个方法主体关联起来被称作绑定。若在程序执行前进行绑定,由编译器和连接程序实现,叫做前期绑定,此为面向过程语言默认绑定方式。

后期绑定:就是在运行时,根据对象的类型进行绑定。后期绑定也叫做动态绑定或运行时绑定。

Java中除了satic方法和final方法之外,其他所有都是后期绑定。

8.2.3 可扩展性

在一个设计良好的OOP程序中,程序是可扩展的,因为可以从通用的基类继承出新的数据类型,从而新添一些功能。那些操作基类接口的方法不需要任何改动就可以应用于新类。

8.2.4 缺陷:覆盖私有方法
  1. public class PrivateOverride {
  2. private void f(){
  3. System.out.println("private f()");
  4. }
  5. public static void main(String[] args){
  6. PrivateOverride po=new Derived();
  7. po.f();
  8. }
  9. }
  10. class Derived extends PrivateOverride{
  11. public void f(){
  12. System.out.println("public f()");
  13. }
  14. }

只有非private方法才可以被覆盖,在导出类中,对于基类的private方法,最好采用不同的名字。

8.2.5 缺陷:域与静态方法
  1. public class FieldAccess {
  2. public static void main(String[] args){
  3. Super sup=new Sub();
  4. System.out.println("sup.feld="+sup.field+",sup.getField()="+sup.getField()+"");
  5. //output:sup.feld=0,sup.getField()=1
  6. Sub sub=new Sub();
  7. System.out.println("sub.field="+sub
  8. .field+",sub.getField()="+sub.getField()+",getSuperField="+sub.getSuperField()+"");
  9. //output:sub.field=1,sub.getField()=1,getSuperField=0
  10. }
  11. }
  12. class Super{
  13. public int field=0;
  14. public int getField(){
  15. return field;
  16. }
  17. }
  18. //Sub包含了两个域,自己的field和继承来的field
  19. class Sub extends Super{
  20. public int field=1;
  21. public int getField(){
  22. return field;
  23. }
  24. public int getSuperField(){
  25. return super.field;
  26. }
  27. }

如果某个方法是静态的,它的行为就不具有多态性

  1. public class StaticPolymorphism {
  2. public static void main(String[] args){
  3. StaticSuper sup=new Staticsub();
  4. System.out.println(sup.staticGet());//output:Base staticGet()
  5. System.out.println(sup.dynamicGet());//output:Derived dynamicGet()
  6. }
  7. }
  8. class StaticSuper{
  9. public static String staticGet(){
  10. return "Base staticGet()";
  11. }
  12. public String dynamicGet(){
  13. return "Base dynamicGet()";
  14. }
  15. }
  16. class Staticsub extends StaticSuper{
  17. public static String staticGet(){
  18. return "Derived staticGet()";
  19. }
  20. public String dynamicGet(){
  21. return "Derived dynamicGet()";
  22. }
  23. }

静态方法是与类,而非与单个的对象相关联

8.3 构造器和多态

构造器并不具有多态性,它们实际上是static方法,只不过该static声明是隐试的。

8.3.1 构造器的调用顺序

基类构造器总是在导出类的构造过程中被调用,而且按照继承层次逐渐向上链接,以使每个基类的构造器都能得到调用。意义:构造器具有一项特殊的任务,检查对象是否被正确的构造。导出类只能访问它自己的成员,不能访问基类中的成员(基类成员通常使private类型)。只有基类的构造器才具有恰到的知识权限来对自己的元素进行初始化。

对象调用构造器遵循以下顺序:

  • 1.调用基类构造器
  • 2.按声明顺序调用成员初始化方法
  • 3.调用导出类构造器的主体
8.3.2 继承与清理

通过组合和继承方法来创建新类时,永远不必担心对象的清理问题,子对象通常都会留给垃圾回收器进行处理。

8.3.3 构造器内部的多态方法的行为

如果调用构造器内部的一个动态绑定方法,就要用到哪个方法的覆盖后的定义。然而,这个调用效果可能难以预测,因为被覆盖的方法在对象完全构造之前就会被调用。

  1. public class PolyConstructors {
  2. public static void main(String[] args){
  3. new RoundGlyph(5);
  4. }
  5. }
  6. class Glyph{
  7. void draw(){
  8. System.out.println("Glyph.draw()");
  9. }
  10. Glyph(){//2
  11. System.out.println("Glyph() before draw()");//3
  12. draw();//4
  13. System.out.println("Glyph() after draw()");//6
  14. }
  15. }
  16. class RoundGlyph extends Glyph{
  17. private int radius=1;//7
  18. RoundGlyph(int r){//1
  19. radius=r;//8
  20. System.out.println("RoundGlyph.RoundGlyph().radius="+radius+"");//9
  21. }
  22. void draw(){
  23. System.out.println("RoundGlyph.draw(),radius="+radius+"");//5
  24. }
  25. }

初始化过程:

  • 1.在其他任何事物发送之前,将分配对象的存储控件初始化成二进制零
  • 2.调用基类构造器
  • 3.按照声明顺序调用成员初始化方法
  • 4.调用导出类的构造器主体

Java编程思想之八多态的更多相关文章

  1. 【学习笔记】JAva编程思想之多态

    1.如果java的基类拥有某个已被多次重载的方法名称,那么在导出类中重新定义该方法名称并不会屏蔽在基类的任何版本.因此,无论是在该层或者他的基类中对方法进行定义,重载机制都可以正常工作. 2.使用@O ...

  2. 《java编程思想》多态与接口

    向上转型 定义:把某个对象的引用视为对其基类类型的引用的做法被称为向上转型方法调用绑定 将一个方法调用同一个方法主体关联起来被称作绑定. 前期绑定:程序执行前进行的绑定叫做前期绑定,前期绑定也是jav ...

  3. (七)《Java编程思想》——多态的缺陷

    1.不能“覆盖”私有方法 package chapter8; /** * 不能"覆盖"私有方法 */ public class PrivateOverride { private ...

  4. Java编程思想(四) —— 复用类

    看了老罗罗升阳的专訪,不由自主地佩服,非常年轻,我之前以为和罗永浩一个级别的年龄.也是见过的不是初高中编程的一位大牛之中的一个,专訪之后.发现老罗也是一步一个脚印的人. 别说什么难做,做不了.你根本就 ...

  5. Java编程思想学习(一)----对象导论中多态的理解

    1.1抽象过程 1)万物皆对象. 2)程序是对象的集合,他们通过发送消息来告知彼此所要求做的. 3)每个对象都有自己的由其他对象所构成的存储. 4)每个对象都拥有其类型. 5)某一特定类型的所有对象都 ...

  6. 《Java编程思想》学习笔记_多态

    多态 多态指一个行为产生多种状态,针对父类类型可接收其子类类型,最终执行的状态由具体子类确定,其不同子类可呈现出不同状态.例如人[父类]都会跑步[行为],但小孩[子类]跑步.成年人[子类]跑步.运动员 ...

  7. 《Java编程思想》学习笔记(二)——类加载及执行顺序

    <Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...

  8. Java编程思想重点笔记(Java开发必看)

    Java编程思想重点笔记(Java开发必看)   Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而 ...

  9. java编程思想-复用类总结

    今天继续读<java 编程思想>,读到了复用类一章,看到总结写的很好,现贴上来,给大家分享. 继承和组合都能从现有类型生成新类型.组合一般是将现有类型作为新类型底层实现的一部分来加以复用, ...

随机推荐

  1. Java程序优化细节

    1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:    1).控制资源的使用,通过线程同 ...

  2. 在safari上,解决fixed失效问题

    一个页面中有头部.底部和中间内容区域,底部固定在屏幕底端. 头部header 内容main 底部footer 方法一.在main上使用fixed定位,加上overflow-y属性. .main { p ...

  3. php+js实现极验,拖动滑块验证码验证表单

    现在很多网站,比如淘宝,京东等都改用使用极验拖动验证码实现登录,这种方式比传统的验证码方式有更好的体验,减少用户输入的错误,也同样能起到防盗刷的功能.现在很多极验都是第三方的,也很多都是收费的.今天在 ...

  4. 【Linux】linux之如何清理磁盘空间

    相关命令: 1.查询磁盘空间占用情况df -h2.进入根目录,查询大文件与目录 cd /du -sh * | sort -n 查看上GB的目录并且排序,可以用这个命令du -h --max-depth ...

  5. 《linux就该这么学》课堂笔记11 LVM、防火墙初识

    1.常用的LVM部署命令 功能/命令 物理卷管理 卷组管理 逻辑卷管理 扫描 pvscan vgscan lvscan 建立 pvcreate vgcreate lvcreate 显示 pvdispl ...

  6. 【还是畅通工程 HDU - 1233】【Kruskal模板题】

    Kruskal算法讲解 该部分内容全部摘录自刘汝佳的<算法竞赛入门经典> Kruskal算法的第一步是给所有边按照从小到大的顺序排列. 这一步可以直接使用库函数 qsort或者sort. ...

  7. Gym - 100962F: Frank Sinatra (树上莫队+bitset)

    题意:给定一棵树,带边权.然后Q次询问,每次给出(u,v),求这个路径上最小的未出现的边权. 思路:树上莫队,求mex可以用分块或者bitset,前者可能会快一点.   莫队过程:求出欧拉序,即记录d ...

  8. MySQL中经典的too many connection怎么破

    文章来源:云栖社区,经同意授权转载 链接:https://yq.aliyun.com/articles/226984?spm=5176.8091938.0.0.nCksaV 错误解决记录:java d ...

  9. Windows Automation API 3.0 Overview

    https://www.codemag.com/article/0810042 While general accessibility requirements (such as font color ...

  10. 同步docker中的容器时间和宿主机相同

    同步docker中的容器时间和宿主机相同.cd /etc/ 在容器中修改下/etc/localtime文件的名称,避免冲突. mv localtime localtime_bak cp /usr/sh ...