什么是多态
所谓多态:就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。 多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
多态性是对象多种表现形式的体现。 现实中,比如我们按下F1
键这个动作:
-
如果当前在
Flash
界面下弹出的就是AS 3
的帮助文档; -
如果当前在
Word
下弹出的就是Word
帮助; -
在
Windows
下弹出的就是Windows
帮助和支持。
同一个事件发生在不同的对象上会产生不同的结果。
多态的实现条件
多态的三个条件:
-
继承的存在(继承是多态的基础,没有继承就没有多态);
-
子类重写父类的方法(多态下调用子类重写的方法);
-
父类引用变量指向子类对象(子类到父类的类型转换)。
子类转换成父类时的规则:
-
将一个父类的引用指向一个子类的对象,称为向上转型(
upcasting
),自动进行类型转换。此时通过父类引用调用的方法是子类覆盖或继承父类的方法,不是父类的方法。 此时通过父类引用变量无法调用子类特有的方法; -
如果父类要调用子类的特有方法就得将一个指向子类对象的父类引用赋给一个子类的引用,称为向下转型,此时必须进行强制类型转换。
以下是一个多态实例的演示,详细说明请看注释:
public class TestAnimalDemo {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat) a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat) a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog) a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
输出结果: 吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠
可以用 instanceof
判断一个类是否实现了某个接口,也可以用它来判断一个实例对象是否属于一个类。instanceof
的语法格式为:
对象 instanceof 类(或接口)
它的返回值是布尔型的,或真(true
)、或假(false
)。 #####多态的实现形式 在Java中有两种形式可以实现多态:继承和接口。
- 基于继承实现的多态
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。
基于继承实现的多态可以总结如下:对于引用子类的父类类型,在处理该引用时,它适用于继承该父类的所有子类,子类对象的不同,对方法的实现也就不同,执行相同动作产生的行为也就不同。
如果父类是抽象类,那么子类必须要实现父类中所有的抽象方法,这样该父类所有的子类一定存在统一的对外接口,但其内部的具体实现可以各异。这样我们就可以使用顶层类提供的统一接口来处理该层次的方法。
- 基于接口实现的多态
继承是通过重写父类的同一方法的几个不同子类来体现的,那么就可能是通过实现接口并覆盖接口中同一方法的几不同的类体现的。
在接口的多态中,指向接口的引用必须是指定实现了该接口的一个类的实例程序,在运行时,根据对象引用的实际类型来执行对应的方法。
继承都是单继承,只能为一组相关的类提供一致的服务接口。但是接口可以是多继承多实现,它能够利用一组相关或者不相关的接口进行组合与扩充,能够对外提供一致的服务接口。所以它相对于继承来说有更好的灵活性。
编程要求
根据提示,在右侧编辑器补充代码:
-
声明一个
Animal
类,此类中定义eat()
方法; -
声明
Dog
类、Cat
类、Lion
类,均继承自Animal
类,并复写了eat()
方法; -
运用多态方式实例化子类对象并调用
eat()
方法打印输出信息; -
具体输出要求请看测试说明。
测试说明
测试输入:无
预期输出: eating bread...
eating rat...
eating meat...
package case8;
public class TestPolymorphism {
public static void main(String[] args) {
// 以多态方式分别实例化子类对象并调用eat()方法
/********* begin *********/
Animal a = new Dog();
a.eat();
Animal b = new Cat();
b.eat();
Animal c = new Lion();
c.eat();
/********* end *********/
}
}
// Animal类中定义eat()方法
abstract class Animal {
/********* begin *********/
abstract void eat();
/********* end *********/
}
// Dog类继承Animal类 复写eat()方法
class Dog extends Animal {
/********* begin *********/
public void eat() {
System.out.println("eating bread...");
}
/********* end *********/
}
// Cat类继承Animal类 复写eat()方法
class Cat extends Animal {
/********* begin *********/
public void eat() {
System.out.println("eating rat...");
}
/********* end *********/
}
// Lion类继承Animal类 复写eat()方法
class Lion extends Animal {
/********* begin *********/
public void eat() {
System.out.println("eating meat...");
}
/********* end *********/
}