您的位置:首页 > 编程语言 > Java开发

JAVA继承和多态

2016-07-17 22:43 225 查看

一、继承

我们把用来做基础派生其它类的那个类叫做父类、超类或者基类,而派生出来的新类叫做子类。Java用关键字extends表示这种继承/派生关系:

class ThisClass extends SuperClass {
//…
}


继承表达了一种is-a关系,就是说,子类的对象可以被看作是父类的对象。比如鸡是从鸟派生出来的,因此任何一只都可以被称作是一只鸟。但是反过来不行,有些鸟是鸡,但并不是所有的鸟都是鸡。如果你设计的继承关系,导致当你试图把一个子类的对象看作是父类的对象时显然很不合逻辑,比如你让鸡类从水果类得到继承,然后你试图说:这只本鸡是一种水果,所以这本鸡煲就像水果色拉。这显然不合逻辑,如果出现这样的问题,那就说明你的类的关系的设计是不正确的。Java的继承只允许单继承,即一个类只能有一个父类。

对理解继承来说,最重要的事情是,知道哪些东西被继承了,或者说,子类从父类那里得到了什么。

答案是:所有的东西,所有的父类的成员,包括变量和方法,都成为了子类的成员,除了构造方法。构造方法是父类所独有的,因为它们的名字就是类的名字,所以父类的构造方法在子类中不存在。除此之外,子类继承得到了父类所有的成员。

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

父类成员访问属性在父类中的含义在子类中的含义
public对所有人开放对所有人开放
protected只有包内其它类、自己和子类可以访问只有包内其它类、自己和子类可以访问
缺省只有包内其它类可以访问如果子类与父类在同一个包内:只有包内其他类可以访问 否则:相当于private,不能访问
private只有自己可以访问不能访问
public的成员直接成为子类的public的成员,protected的成员也直接成为子类的protected的成员。Java的protected的意思是包内和子类可访问,所以它比缺省的访问属性要宽一些。而对于父类的缺省的未定义访问属性的成员来说,他们是在父类所在的包内可见,如果子类不属于父类的包,那么在子类里面,这些缺省属性的成员和private的成员是一样的:不可见。父类的private的成员在子类里仍然是存在的,只是子类中不能直接访问。我们不可以在子类中重新定义继承得到的成员的访问属性。

如果我们试图重新定义一个在父类中已经存在的成员变量,那么我们是在定义一个与父类的成员变量完全无关的变量,在子类中我们可以访问这个定义在子类中的变量,在父类的方法中访问父类的那个。尽管它们同名但是互不影响。

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

父类的private类型的东西,子类不能碰,但是可以通过父类的函数去碰。
子类中任何地方可通过super.父类函数来调用父类函数
使用protected是实在没办法的时候才用的。
可以通过super.父类公有函数来调用父类的public函数。
只有父类的函数才可以调用父类的私有变量和私有函数。


二、多态

多态变量

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

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

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

Car myCar = new Car();


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

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


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

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

向上造型

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

拿一个子类对象,当作父类对象来用。

向上造型是默认的,不需要运算符。

向上造型总是安全的

造型cast

父类的对象不能赋值给子类的变量

子类的对象可以赋值给父类的变量

注意JAVA中不存在对象与对象之间的赋值

//  Vechicle派生出了子类Car
Vechicle v;
Car c = new Car();
v=c;//可以
c=v;//编译错误!


可以用造型

// (只有当v这个变量实际管理的是Car才行)
c=(Car) v;//此时编译器会允许通过,但是编译的时候可能会出错


函数调用的绑定

当通过对象变量调用函数的时候,调用哪个函数这件事情叫做绑定

静态绑定:根据变量的声明类型来决定

动态绑定:根据变量的动态类型来决定(JAVA语言默认所有绑定都是动态的)

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

覆盖override

子类和父类中存在名称和参数完全相同的函数,这一函数构成覆盖关系

通过父类的变量调用存在覆盖关系的函数时,会调用变量当时所管理的对象的类的函数

你是一个Shape,那么你就应该会draw,那么,你就去draw吧

(Shape就是父类,你就是一切子类,draw就是父类中的一个public函数,而且在所有子类中都有同名的draw函数,那么在运行的时候,会自动调用每个子类的同名函数)

三、Object类

@Override告诉了编译器,下面的函数完全覆盖了父类的某一个对应的函数,如果有一个地方不相同,那么编译器就会显示编译错误,是一个很好的保证正确的方法。

- Object类的函数

toString();

equals();

- toString()

只要类中有toString()函数的定义,那么在之后需要toString()函数的时候会自动调用子类的toString()函数。

super.toString()会调用父类的toString()

equals()

//也是父类中的一个函数,用法同上

public boolean equals(Object obj){

return super.equals(obj); //可改写成自己的操作

} <
4000
br>
如果不带@Override,然后把equals的参数增加,如:equals(Object obj,int i)那么在调用子类的equals的时候,如果不带哪个i,就会进到父类的equals而不会进到子类这个

DOME新的媒体类型,只要继承那个媒体的父类,往下设计自己的结构或者函数,就可以了。

可以利用更深的继承关系来更加有效的表达各种媒体之间的关系,将共同都有的元素,函数放到共同的父类中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: