java继承涉及的动/静态绑定及隐藏

项目中经常会用到java多态这个特性,之前只知道一些皮毛,现在发现自己对它并没有一个系统的认识,想从新梳理下自己的基础库。

看了java编程思想中对象导论,关于继承的描述:java中的类型不仅仅只是描述了作用于一个对象集合上的约束条件,同时还有与其他类型的之间的关系。可以创建一个基类来表示系统中某些对象的核心概念,从基类的基础上导出其他的类型,用以表示此核心可以被实现的不同方式。因此我们知道了类与类之间还有继承的关系。

问题:那什么是多态呢?多态跟继承有什么关系?

假设我编写了一个基类,它有多个导出类, 每次因我们调用导出类的方法而创建自己对象时,n多个导出类有可能创建n个导出类对象。

java中多态给我们带来的好处是可以不用创建具体的导出类对象,而是基类的对象,去调用各自的方法。这种情形在书中描述的是:在处理类型层次结构时,经常想把一个对象不当做它所属的特定类型对待,而是当做基类对象对待。

例如:SAO是一个基类,AliSAO和WeixinSAO是其导出类,都有一个相同的hello方法

按照自己之前老套路就是:

AliSAO aliSAO = new AliSAO();

aliSAO .hello();

... ...

如果有n个导出类,就会有n个不同类型的对象

... ...

现在把导出类的类型改成基类,交由java这种多态,使得我们可以编写出不依赖特定类型的编码。  

SAO aliSAO = new AliSAO();
SAO weixinSAO = new WeixinSAO();

aliSAO.hello()和weixinSAO.hello()

aliSAO和weixinSAO对象可以统一用 SAO类型

这样的代码是受新添加代码影响较小。

但是这样子会引出一个问题:把导出类对象当做泛化的基类类型对象,此对象本身怎么确定去执行正确的方法呢?

一个非面向对象编程的编译器产生的函数调用会引起所谓的前期绑定,编译器将产生一个具体的函数名称的调用,运行时这个调用会解析到具体代码的绝对地址上.而不会出现像java这种泛化对象的不确定性方法调用。

如果是private、static、final 方法或者是构造器,则编译器明确地知道要调用哪儿个方法,这种调用方式成为“静态调用”.动态绑定只是针对对象的非private,static,final方法.

而面向对象编程中,这种情形在编译期间是无法确定具体调用那个方法的,SAO类型对象(aliSAO和weixinSAO )在没有运行时不能确定它具体类型(有人觉得SAO aliSAO = new AliSAO();不就能知道是AliSAO类型泛化的,此时是在编译期间,对象都没有创建,虚拟机根本不知道,好比你自己心里想的自己很清楚,你想让别人知道,首先你得说出来,这个说出来就是运行),hello()方法都不知道调用自己的SAO对象是基类还是导出类。

为了解决这个问题面向对象程序设计语言提出了后期绑定的概念:java使用一小段代码代替了绝对地址调用,这段代码使用了对象中存储的信息来计算方法的地址.

这样一来,每个对象根据这段代码的内容,可以具有不同的行为表现,当向一个对象发送消息时,该对象就能够做出相应的应答.

上面说的都是实例方法,如果是类的静态属性和静态方法能否继承?

答案是可以的.只是这种继承有个特性,叫隐藏.当子类属性和方法跟父类相同时,会出现隐藏现象.如下图:

java的多态之所以能现实是依赖于父子类继承,接口实现,重写和重载.有了继承,可以通过子类对象指向父类引用,有了重写,可以通过父类引用的子类对象访问子类重写的方法,而不是父类的方法,这是因为“重写”后子类的方法优先级要高于父类的优先级.而隐藏却没有这个属性,因此在如图中通过Parent ps = new Son();ps.getName()是非静态方法,调用的是子类重写的方法,ps.getAge()是静态方法,只能调用父类的方法!

切记上面说的导出类继承基类方法的覆盖后,导出类的非静态的方法优先级要高,如果是属性呢?

如果注意到了:

Parent ps = new Son();
System.out.println(ps.age);// 返回父类的age=30

System.out.println(ps.money);// 返回父类的money=500

System.err.println(ps.name);// ‘jack‘

其中age和money在基类和导出类中都是静态变量.而name是非静态变量.

就会知道基类与导出类的属性覆盖是没有优先级的,获取的都是基类的属性值.它跟具体对象类型是没关系的,只跟对象引用类型有关!

重写只是发生在父子类继承的的方法中,属性是没有重写这一说法的.当导出类有和基类相同 名称的属性时(甚至类型都可以不同)基类的属性会被隐藏

对于子类来说,父类的属性是不能被子类对象引用访问到的,而需要通过其父类对象的引用访问;通常来说,我们不建议隐藏属性,因为这会使代码不易阅读;

从以上定义可以看出,成员属性不能像方法那样被重写,当子类定义了一个和其父类相同名字的成员属性,子类仅仅是声明了一个新的属性,而其父类的属性被隐藏起来,这不是重写,实际上用super.属性名,还是可以得到父类的非private属性,所以不能以多态的形式访问。

向上转型:将导出类看成是基类的过程就是向上转型,前面提到的SAO aliSAO = new AliSAO();即是向上转型,其实际对象是AliSAO导出类的对象,引用的却是是基类.

只能导出类对象向上转型基类对象,反之则不能(如果基类对象能转型成导出类对象,会出现该对象丢失导出类的行为或属性,毕竟导出类的属性和方法要等于或多于基类).

时间: 03-26

java继承涉及的动/静态绑定及隐藏的相关文章

java中的动态绑定与静态绑定

首先是方法的参数是父类对象,传入子类对象是否可行 然后引出Parent p = new Children(); 这句代码不是很理解,google的过程中引出向上转型 要理解向上转型又引出了动态绑定 从动态绑定又引出了静态绑定   程序绑定的概念: 绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来.对java来说,绑定分为静态绑定和动态绑定:或者叫做前期绑定和后期绑定   静态绑定: 在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现.例如:C. 针对java简单的可以理解为程序

Java 继承和多态

                                                    Java  继承和多态 Java 继承 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为. 生活中的继承: 兔子和羊属于食草动物类,狮子和豹属于食肉动物类. 食草动物和食肉动物又是属于动物类. 所以继承需要符合的关系是:is-a,父

Java继承与组合

Java继承与组合 继承 java 中使用extends关键字表示继承关系,当创建一个类时,如果没有明确指出要继承的类,则是隐式地从根类Object进行继承. 子类继承父类的成员变量 子类能够继承父类的public和protected成员变量,不能够继承父类的private成员变量 如果在子类中出现了同名称的成员变量,则子类的成员变量会屏蔽掉父类的同名成员变量.若要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用. public class Main { /** * @para

java 继承之间方法的时候(计算出经理与员工之间公司差别)

自己检讨下:刚开始看这个的时候,我觉得挺简单的,但是让我自己写的时候我确实不会写,最大的缺点就是好高骛远,偷懒,基础不会就想着上天. 希望别的朋友别要有这样的想法,再简单的例子,如果你不亲自敲下,在揣摩下,你敢说日后让你写这样的代码,你能写出来吗,我不是天才,但我坚信勤奋可以造就天才. 首先:分析下员工与经理之间的相同点,就是员工与经理都有姓名,工资和日期(其实我感觉这个日期不必要有)这个三个属性,经理比员工多的就是经理又项目奖金 然后可以把相同的信息抽出来,实例一个Employee类 ,这个类

Java面向对象程序设计--与C++对比说明:系列3(Java 继承机制)

继承(inheritance)背后的核心思想是:可以在现有类的基础上创建自己的新类,在新类中继承原来类的方法和数据域,并添加适合当前应用场景的新的数据和方法. 1. 类,超类,子类 (class,superclass,subclass): Java 中的inheritance都是public inheritance,并不想C++中存在public,protected和private inheritance的分类. class subclass extends superclass; 这里有两个要

Java-Runoob-面向对象:Java 继承

ylbtech-Java-Runoob-面向对象:Java 继承 1.返回顶部 1. Java 继承 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为. 生活中的继承: 兔子和羊属于食草动物类,狮子和豹属于食肉动物类. 食草动物和食肉动物又是属于动物类. 所以继承需要符合的关系是:is-a,父类更通用,子类更具体. 虽然食草动物和食肉

java继承和多态

java方法直接调用原理推测 有错误还望指正 当直接调用某对象的某方法时  会更具该对象获取到类信息对象   在从类信息对象中找到该方法 没找到 获取父类信息对象继续查找 找到了执行  jdk距离实现是通过反射还是其它? 如果按以上原理    以下情况解释不通 创建一子类对象  赋值给一父类指针变量  通过父类指针变量掉run方法   run方法在父类或子类中为私有  这种情况调用的是父类的run方法 并非子类的run方法 反射jar包 package extend; import org.ju

Java继承,多态,组合应用

继承:  面向对象的三大特征之一:    是类和类之间的一种拓展关系,是一种从一般到特殊的关系;    格式: sub   extends Super,  我们把sub称为子类或者拓展类, 把super称为父类或者基类(超类)   泛化: 把子类中的共性抽取到父类的过程; 特化: 子类在父类的基础之上,拓展自己特有的状态和特征;    Object: 是所有类的直接父类后间接父类;      class  Student{} 等价于  class  Student extends Object{

Java继承

public class Employee { public static String superStr = "SUPERSTR"; public String test() { return "SUPERTEST"; } public String test2() { return "SUPERTEST2"; } } public class Manager extends Employee { public static void main