正文
目前为止,我们已经学习了封装、继承,三大特性还有一个是多态性,本节来学习多态。
多态基本上总是与继承有关系的。
多态是类型理论中的一个概念,即一个名字可能代表许多不同类的实例,只要它们都有共同的超类。于是,由这个名字所代表的对象就能够以不同的方式对同一组操作做出反应。利用多态,一个操作可以被层次结构中的类以不同的方式实现。通过这种方式,子类可以扩展超类的能力,或者覆盖父类的操作。这种情况被称之为“重写”。
在Java中,开发者可以在一个类体内,用同样的名字来定义方法,只要它们的调用可以通过方法签名来区别,这种情况被称之为“重载”。方法签名由参数的个数和数据类型构成,在重载解析时不考虑方法的返回值类型的。
另外,方法的参数也可以是多态的,我们称之为“多态参数”,这是我们今天讨论的重点。
多态性
多态性是面向对象的三大特征之一
多态的含义是:对外一种表现形式,内在有多种具体实现。
Java中多态的具体体现
方法重载
方法覆盖
多态参数(新内容,重点、难点)
运行期类型与编译期类型
运行期类型与编译期类型
第一种情况:编译期类型和运行期类型相同
A a = new A();
a.show();
声明A的时候,使用到的类型A表示对象的类型,被称为编译期类型,在编译期,虚拟机认为a的类型是A,对于a所使用的属性和方法的有效性将到类A中去验证。
构造方法A()中的A是运行期类型,在运行期,将执行运行期类型中的方法
运行期类型与编译期类型
第二种情况:当有继承关系时,可能发生编译期类型和运行期类型不同的情况,即编译期类型是父类类型,运行期类型是子类类型。
//A类是B类的父类
A ab = new B();
ab.show();
对象ab的编译期类型为父类A类,运行期类型为子类B类。
如果一个引用的编译期类型和运行期类型不同,那么一定是编译期类型与运行期类型有父类子类关系。
ab对象使用的方法,在编译期到类A中去校验,而运行则执行B类的方法
如果一个对象的编译期类型是父类,运行期类型是子类,可以对该对象进行强制类型转换,将其编译器类型转换为与运行期类型相同的类型,即:B b=(B)ab;
父类引用指向子类对象
当编译器类型是父类,运行期类型是子类时,被称为父类引用指向子类对象
class Animal{
……
}
class Cat extends Animal{
……
}
class Dog extends Animal {
……
}
Cat m = new Cat()
Animal x = new Cat() //Animal 的引用指向Cat的对象
对象m可以调用猫类中的所有方法,x只能调用动物类中定义的方法,
猫类扩展的新方法不能调用。
多态环境下对成员方法的调用
多态环境下对成员方法的调用
class Animal{
void show() {
System.out.println(“Anmial");
}
}
class Cat extends Animal{
void show() {
System.out.println(“cat");
}
}
…….
Animal x = new Cat()
x.show() //调用的是子类中的方法
简单的说:编译看左边,运行看右边。
多态环境下对静态成员方法的调用
class Animal{
static void show() {
System.out.println(“Animal");
}
}
class Cat extends Animal {
static void show() {
System.out.println(“Cat");
}
}
…….
Animal x = new Cat()
x.show() //调用的是动物类中的静态成员方法。
简单的说:编译和运行都看左边。
多态环境下对成员变量的调用
class Animal{
int num = 3;
}
class Cat extends Animal {
int num = 4;
}
…….
Animal x = new Cat()
x.num; //调用的是动物类中的成员变量。
简单的说:编译和运行都看等号左边。
注意:变量不存在被子类覆写这一说法,只有方法存在覆写。
多态参数
前面我们反复学习的就是父类引用指向子类对象,实际编程过程中,我们往往是在参数中使用这种特性。
方法参数具有多态性
class Animal{
void eat() {}
}
class Cat extends Animal{
void eat() {}
}
class Dog extends Animal{
void eat(){}
}
//方法的形式参数类型是父类类型,而传递的实际参数可以是任意子类的对象
method(Animal animal){
animal .eat();
}
方法参数多态性的好处:提高代码的扩展性
多态环境下对象造型
当存在多态环境时,有时候需要类型转换。这里将涉及到一个概念叫 强制类型转换,但是记住,强制是有前提的,只能强制转换成这个对象的运行期类型
例如
Animal animal=new Cat();
Cat cat=(Cat)animal;
因为animal的运行期类型确实是Cat,所以才可以强制转换成Cat
如果 Dog dog=(Dog)animal;
将发生ClassCastException
向上造型 –又称自动类型提升
class Animal{
abstract void eat();
}
class Cat extends Animal{
void look() {
System.out.println("看家");
}
}
………
Animal x=new Cat() //向上造型,Cat对象提升到Animal对象
x.eat() //只能使用父类中的方法
x.look() //报错!不能使用子类中的方法
向上造型的作用是:提高程序的扩展性。