4.3多态变量和向上造型
类定义了类型,DVD类所创建的对象的类型就是DVD。类可以有子类,所以由那些类定义的类型可以有子类型。在DoME的例子中,DVD类型就是Item类型的子类型。
子类型类似于类的层次,类型也构成了类型层次。子类所定义的类型是其超类的类型的子类型。
当把一个对象赋值给一个变量时,对象的类型必须与变量的类型相匹配,如:
Car myCar = new Car();
是一个有效的赋值,因为Car类型的对象被赋值给声明为保存Car类型对象的变量。但是由于引入 了继承,这里的类型规则就得叙述得更完整些:
一个变量可以保存其所声明的类型或该类型的任何子类型。
对象变量可以保存其声明的类型的对象,或该类型的任何子类型的对象。
Java中保存对象类型的变量是多态变量。“多态”这个术语(字面意思是许多形态)是指一个变量可以保存不同类型(即其声明的类型或任何子类型)的对象。
子类和子类型
- 类定义了类型
- 子类定义了子类型
- 子类的对象可以被当作父类的对象来使用
- 赋值给父类的变量
- 传递给需要父类对象的函数
- 放进存放父类对象的容器中
子类型与赋值
子类的对象可以复制给父类变量
Vehicle v1=new Vehicle();
Vehicle v2=new Car();
Vehicle v3=new Bicycle();
子类与参数传递
子类的对象可以赋值给需要父类对象的函数
子类型和容器
子类的对象可以放在存放父类对象的容器中
多态变量
- Java的对象变量是多态的,它们能保存不止一种类型的对象
- 他们可以保存的是声明类型的对象,或声明类型子类的对象
- 当把子类的对象赋给父类的变量的时候,就发生了向上造型
造型cast
- 子类的对象可以赋值给父类的变量
- 注意!Java中不存在对象对对象的赋值!!
- 父类的对象不能赋值给子类的变量
Vehicle v; Car c=new Car; v-c;//可以 c=v;//编译错误!
- 可以用造型 c=(Car)v;
- (只有当v这个变量实际管理的是Car才行)
Item item =new Item("a",0,true,"…"); CD cd=new CD("a","a",0,0,"…"); item=cd; CD cc=(CD)item;
- 用括号围起类型放在值的前面
- 对象本身并没有发生任何变化(区别类型转化)
- 所以不是类型转化
- 运行时有机制来检查这样的转化是否合理
- ClassCastException
向上造型
- 拿一个子类的对象当作父类的对象来用
- 向上造型是默认的,不需要运算符
- 向上造型总是安全的
4.4多态
如果子类的方法覆盖了父类的方法,我们也说父类的那个方法在子类有了新的版本或者新的实现。覆盖的新版本具有与老版本相同的方法签名:相同的方法名称和参数表。因此,对于外界来说,子类并没有增加新的方法,仍然是在父类中定义过的那个方法。不同的是,这是一个新版本,所以通过子类的对象调用这个方法,执行的是子类自己的方法。
覆盖关系并不说明父类中的方法已经不存在了,而是当通过一个子类的对象调用这个方法时,子类中的方法取代了父类的方法,父类的这个方法被“覆盖”起来而看不见了。而当通过父类的对象调用这个方法时,实际上执行的仍然是父类中的这个方法。注意我们这里说的是对象而不是变量,因为一个类型为父类的变量有可能实际指向的是一个子类的对象。
当调用一个方法时,究竟应该调用哪个方法,这件事情叫做绑定。绑定表明了调用一个方法的时候,我们使用的是哪个方法。绑定有两种:一种是早绑定,又称静态绑定,这种绑定在编译的时候就确定了;另一种是晚绑定,即动态绑定。动态绑定在运行的时候根据变量当时实际所指的对象的类型动态决定调用的方法。Java缺省使用动态绑定。
函数调用的绑定
- 当通过对象变量调用函数的时候,调用哪个函数这件事情叫做绑定
- 静态绑定:根据变量的声明类型来决定
- 动态绑定:根据变量的动态类型来决定
- 在成员函数中调用其他成员函数也是通过this这个对象变量来调用的
覆盖override
- 子类和父类中存在名称和参数表完全相同的函数,这一对函数构成覆盖关系
- 通过父类的变量调用存在覆盖关系的函数时,会调用变量当时所管理的对象所属的类的函数
4.5系统类型
Object类–所有类都是继承自Object的
Object类的函数
- toString();//用一个字符串表达那个对象
- equals();//比较内容是否相同
可扩展性:给Item新增一个Game
package demo;
public class Game extends Item {
private int numOfPlayers;
public Game(String title, int playingTime, String comment,int numOfPlayers) {
super(title, playingTime, false, comment);
this.numOfPlayers=numOfPlayers;
// TODO Auto-generated constructor stub
}
@Override
public void print() {
// TODO Auto-generated method stub
System.out.print("Game:");
super.print();
System.out.println(":"+numOfPlayers);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}