Java-复习继承与多态,绑定

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oqzuser1q2w3e4r5t/article/details/88894816

一、继承

对理解继承来说,最重要的事情是,知道哪些东西被继承了,或者说,子类从父类那里得到了什么。答案是:所有的东西,所有的父类的成员,包括变量和方法,都成为了子类的成员,除了构造方法。构造方法是父类所独有的,因为它们的名字就是类的名字,所以父类的构造方法在子类中不存在。除此之外,子类继承得到了父类所有的成员。

但是得到不等于可以随便使用。每个成员有不同的访问属性,子类继承得到了父类所有的成员,但是不同的访问属性使得子类在使用这些成员时有所不同:有些父类的成员直接成为子类的对外的界面,有些则被深深地隐藏起来,即使子类自己也不能直接访问。下表列出了不同访问属性的父类成员在子类中的访问属性:

父类成员访问属性

在父类中的含义

在子类中的含义

public

对所有人开放

对所有人开放

protected

只有包内其它类、自己和子类可以访问

只有包内其它类、自己和子类可以访问

缺省

只有包内其它类可以访问

如果子类与父类在同一个包内:只有包内其它类可以访问

否则:相当于private,不能访问

private

只有自己可以访问

不能访问

public的成员直接成为子类的public的成员,protected的成员也直接成为子类的protected的成员。

Java的protected的意思是包内和子类可访问,所以它比缺省的访问属性要宽一些。而对于父类的缺省的未定义访问属性的成员来说,他们是在父类所在的包内可见,如果子类不属于父类的包,那么在子类里面,这些缺省属性的成员和private的成员是一样的:不可见。

父类的private的成员在子类里仍然是存在的,只是子类中不能直接访问。我们不可以在子类中重新定义继承得到的成员的访问属性。如果我们试图重新定义一个在父类中已经存在的成员变量,那么我们是在定义一个与父类的成员变量完全无关的变量,在子类中我们可以访问这个定义在子类中的变量,在父类的方法中访问父类的那个。尽管它们同名但是互不影响。

在构造一个子类的对象时,父类的构造方法也是会被调用的,而且父类的构造方法在子类的构造方法之前被调用。在程序运行过程中,子类对象的一部分空间存放的是父类对象。因为子类从父类得到继承,在子类对象初始化过程中可能会使用到父类的成员。所以父类的空间正是要先被初始化的,然后子类的空间才得到初始化。在这个过程中,如果父类的构造方法需要参数,如何传递参数就很重要了。

子类方法:

CD继承了Item的所有方法,但是在执行过程中,Item会先进行初始化,Item的定义初始化和构造器一定会先做,做完后,CD才开始初始化自己的,不管CD类有没有通过Super去调用。即使CD类调用了Super类但又不进行传参的话,Item类也会执行它的空构造方法。

父类方法:

二、多态

类定义了类型,DVD类所创建的对象的类型就是DVD。类可以有子类,所以由那些类定义的类型可以有子类型。

子类型类似于类的层次,类型也构成了类型层次。子类所定义的类型是其超类的类型的子类型。

当把一个对象赋值给一个变量时,对象的类型必须与变量的类型相匹配,如:

     Car myCar = new Car(); 

是一个有效的赋值,因为Car类型的对象被赋值给声明为保存Car类型对象的变量。但是由于引入 了继承,这里的类型规则就得叙述得更完整些:

    一个变量可以保存其所声明的类型或该类型的任何子类型

对象变量可以保存其声明的类型的对象,或该类型的任何子类型的对象。

Java中保存对象类型的变量是多态变量。“多态”这个术语(字面意思是许多形态)是指一个变量可以保存不同类型(即其声明的类型或任何子类型)的对象。

总结一下:

 

 如下图中:

Databast是父类

DVD、CD类是子类

 

总结:

一个对象至少有两个类型,以上图的item类型为例,它的静态类型是已经定义的类型。它的动态类型是它要管理的对象类型。

多态变量的含义:这个对象在某个时刻它所管理的对象类型是会变化的,所以这才是多态。

向上造型:当把子类的对象赋给父类的变量的时候,就发生了向上造型。

Java的对象变量是多态的,它们能保存不止一种类型的对象。

对象变量可以保存的是声明类型的对象,或声明类型的子类的对象。

三、绑定

如果子类的方法覆盖了父类的方法,我们也说父类的那个方法在子类有了新的版本或者新的实现。覆盖的新版本具有与老版本相同的方法签名:相同的方法名称和参数表。因此,对于外界来说,子类并没有增加新的方法,仍然是在父类中定义过的那个方法。不同的是,这是一个新版本,所以通过子类的对象调用这个方法,执行的是子类自己的方法。

覆盖关系并不说明父类中的方法已经不存在了,而是当通过一个子类的对象调用这个方法时,子类中的方法取代了父类的方法,父类的这个方法被“覆盖”起来而看不见了。而当通过父类的对象调用这个方法时,实际上执行的仍然是父类中的这个方法。注意我们这里说的是对象而不是变量,因为一个类型为父类的变量有可能实际指向的是一个子类的对象。

当调用一个方法时,究竟应该调用哪个方法,这件事情叫做绑定。

绑定表明了调用一个方法的时候,我们使用的是哪个方法。

绑定有两种:一种是早绑定,又称静态绑定,这种绑定在编译的时候就确定了;

另一种是晚绑定,即动态绑定。动态绑定在运行的时候根据变量当时实际所指的对象的类型动态决定调用的方法。

Java缺省使用动态绑定。

在成员函数里调用其他成员函数也是通过this这个对象变量来调用的

猜你喜欢

转载自blog.csdn.net/oqzuser1q2w3e4r5t/article/details/88894816