面向对象三大特性(三):多态
多态是对继承的扩展机制,指的是父类的引用指向子类的对象。
多态实现的前提条件是:
- 有继承关系
- 子类重写了父类方法
- 父类的引用调用子类的实现
我们继续继承 的代码继续修改。在os包下新建一个MacOSX类继承OS。
public class MacOSX extends OS {
public MacOSX() {
super();
this.name = "MacOSX";
}
@Override
public void logOff() {
//super.logOff();
System.out.println("保存窗口状态。。。");
System.out.println("正在注销。。。");
System.out.println("3秒后");
System.out.println("注销成功");
}
}
注意一下,现在OS和它的两个子类Windows、MacOSX都有logOff方法,但是这三个logOff的实现并不相同。
然后使用以下测试代码:
DeskTop deskTop = new DeskTop();
System.out.println("**********");
deskTop.setOS(new OS()); //装了dos系统
deskTop.getOS().logOff();
System.out.println("**********");
deskTop.setOS(new Windows()); //装了Windows系统
deskTop.getOS().logOff();
System.out.println("**********");
deskTop.setOS(new MacOSX()); //装了MacOSX系统
deskTop.getOS().logOff();
运行结果:
<pre>
一台新的电脑诞生了。
这是一台台式机
关闭所有正在运行的程序。。。
关闭所有正在运行的程序。。。
正在注销。。。
10秒后
注销成功
保存窗口状态。。。
正在注销。。。
3秒后
注销成功
</pre>
首先以下这部分非常简单,创建一个台式机,然后传进去一个系统,也就是一个OS类的对象。然后调用OS类的logOff方法,这一切合情合理没什么好说的。
DeskTop deskTop = new DeskTop();
System.out.println("**********");
deskTop.setOS(new OS()); //装了dos系统
deskTop.getOS().logOff();
System.out.println("**********");
然后以下这部分就要说说了,首先setOS()的参数是OS,居然能传进去OS的子类Windows和MacOSX的对象。其次logOff()的执行的是传进来的Windows和MacOSX对象的logOff()而不是OS类的logOff()。这就是所谓的多态,再重复再开始那句话:父类的引用指向子类的对象。
deskTop.setOS(new Windows()); //装了Windows系统
deskTop.getOS().logOff();
System.out.println("**********");
deskTop.setOS(new MacOSX()); //装了MacOSX系统
deskTop.getOS().logOff();
其实以上原理就是:
OS win = new Windows();
OS mac = new MacOSX();
可以把这两个语句拆成两部分
- 声明部分:<code>OS win</code>和<code>OS mac</code>
- 实例化部分:<code>new Windows();</code>和<code>new MacOSX();</code>
多态就是只要声明部分的类和实例化部分的类有继承关系,父类的引用就可以指向子类的对象。也就是示例中的
deskTop.setOS(new OS());
deskTop.setOS(new Windows());
deskTop.setOS(new MacOSX());
父类对象OS()出现的地方子类对象Windows()和MacOSX()也可以出现。
另外对象属性的值或者方法具体实现取决于实例化部分的类而不取决于声明的部分的类。所以
deskTop.getOS().logOff();
同一个语句出现了三个不同结果。
关于多态还有一点要注意,就是虽然对象的属性的值和方法的具体实现取决于实例化部分的类,但是对象可以调用的属性和方法取决于声明部分的类。
例如,如果在Windows类里添加以下属性和方法。
protected String Wallpaper; //壁纸
public void showUI() {
System.out.println("显示图形界面");
}
然后创建一个OS的引用指向Windows对象。
OS win = new Windows();
win. //OS的引用无法调用Windows实例的属性和方法
这个时候win是无法调用Windows的属性和方法的,因为win能调用的方法取决于声明它的OS类有没有这个属性和方法。
本文代码下载:百度网盘