18. 面向对象三大特性之多态性
18.1 多态的定义
代码当中体现多态性,其实就是一句话:父类引用指向子类对象.
格式:
或者:
父类:
1 2 3 4 5 6 7 8 9 10 11
| package com.tipdm3.Demo01;
public class Fu { public void method(){ System.out.println("父类方法"); }
public void methodFu(){ System.out.println("父类特有方法!"); } }
|
子类:
1 2 3 4 5 6 7 8
| package com.tipdm3.Demo01;
public class Zi extends Fu{ @Override public void method() { System.out.println("子类方法"); } }
|
主类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.tipdm3.Demo01;
public class demo1 { public static void main(String[] args) { Fu obj = new Zi();
obj.method(); obj.methodFu(); } }
|
1 2 3 4
| 子类方法 父类特有方法!
进程已结束,退出代码0
|
多态成员变量的访问
访问成员变量的两种方式:
直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找
间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找
父类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.tipdm3.Demo02;
public class Fu{ int num = 10; public void showNum(){ System.out.println(num); }
public void method(){ System.out.println("父类方法"); }
public void methodFu(){ System.out.println("父类特有方法"); } }
|
子类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.tipdm3.Demo02;
public class Zi extends Fu{ int num = 20; int age = 18;
@Override public void showNum() { System.out.println(num); }
@Override public void method(){ System.out.println("子类方法"); }
public void methodZi() { System.out.println("子类特有方法"); } }
|
主类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.tipdm3.Demo02;
public class demo01 { public static void main(String[] args) { Fu obj = new Zi(); System.out.println(obj.num);
System.out.println("============="); obj.showNum(); } }
|
1 2 3 4 5
| 10 ============= 20
进程已结束,退出代码0
|
到这里,其实可以做一个小总结;多态其实就是为了使用子类对父类中的某些方法进行修改,而不影响父类中其他功能的正常运行。
多态成员方法的访问
在多态的代码当中,成员方法的访问规则是:
看new的是谁,就优先用谁,没有就向上找
口诀:
主类(子类和父类同上节):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.tipdm3.Demo02;
public class demo02 { public static void main(String[] args) { Fu obj = new Zi();
obj.method(); obj.methodFu();
} }
|
1 2 3 4
| 子类方法 父类特有方法
进程已结束,退出代码0
|
对比一下多态中访问成员变量和方法的不同点:
- 成员变量: 编译看左边,运行还看左边
- 成员方法: 编译看左边,运行看右边
18.4 多态的向上转型和向下转型
- 向上转型一定是安全的,没有问题的,正确的.
- 但是有一个弊端:
- 对象一旦向上转型成为父类,那么就无法调用子类原本特有的内容.
- 解决方案:用对象的向下转型【还原】.
- 本来是猫才能还原成为猫
父类:
1 2 3 4 5
| package com.tipdm3.Demo03;
public abstract class Animal { public abstract void eat(); }
|
子类——猫:
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.tipdm3.Demo03;
public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); }
public void catchMouse(){ System.out.println("猫抓老鼠"); } }
|
子类——狗
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.tipdm3.Demo03;
public class Dog extends Animal{ @Override public void eat() { System.out.println("狗吃骨头"); }
public void watchHouse(){ System.out.println("狗看家"); } }
|
主类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.tipdm3.Demo03;
public class demo1 { public static void main(String[] args) { Animal animal = new Cat(); animal.eat();
Cat animal1 = (Cat) animal; animal1.catchMouse();
} }
|
如何保证使用向下转型不会出错呢?
- 加上对象类型判断即可
- 使用instanceof方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.tipdm3.Demo03;
public class demo2Instanceof { public static void main(String[] args) { Animal animal = new Dog(); animal.eat(); giveMeAPet(animal); }
public static void giveMeAPet(Animal animal){ if (animal instanceof Dog) { Dog dog = (Dog) animal; dog.watchHouse(); }
if (animal instanceof Cat){ Cat cat = (Cat) animal; cat.catchMouse(); } } }
|
接口和多态综合案例:定义USB接口,具备最基本的开启功能和关闭功能.
鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,实现USB接口,否则鼠标和键盘的生成出来也无法使用.
分析:
一共有电脑,鼠标,键盘三个类,并且三个类都属于电子产品。他们都有开启、关闭、使用设备功能。其中,鼠标和键盘是USB设备,需要遵循USB接口协议。
最终项目结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| USB —— USB接口 { public abstract void open(); public abstract void close(); public abstract void use(); } ElectronicProduct —— 电子产品(父类,遵行USB接口协议)
{ String name; boolean STATE_OPEN; open(); use(); close(); usbFunction(); showState(); }
Computer—— 电脑(ElectronicProduct 子类) { useUSBDevice(); }
Mouse —— 鼠标(ElectronicProduct 子类) { usbFunction(); }
KeyBoard —— 键盘(ElectronicProduct 子类) { usbFunction(); }
|
USB接口:
1 2 3 4 5 6 7 8 9
| package com.tipdm3.Demo04;
public interface USB { public abstract void open();
public abstract void close();
public abstract void use(); }
|
ElectronicProduct类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| package com.tipdm3.Demo04;
public class ElectronicProduct implements USB{ private String name; private boolean STATE_OPEN = false;
public ElectronicProduct(String name) { this.name = name; }
public ElectronicProduct() { }
@Override public void open() { System.out.println("打开" + this.name); this.STATE_OPEN = true; }
@Override public void close() { System.out.println("关闭" + this.name); this.STATE_OPEN = false; }
@Override public void use() { if (this.STATE_OPEN) { this.usbFunction(); }else{ System.out.println("请先开启" + this.name); } }
public void usbFunction(){ System.out.println("=============USB功能============="); }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public boolean isSTATE_OPEN() { return STATE_OPEN; }
public void setSTATE_OPEN(boolean STATE_OPEN) { this.STATE_OPEN = STATE_OPEN; }
public void showState(){ System.out.println(this.name + " State:" + this.STATE_OPEN); }
}
|
Computer类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.tipdm3.Demo04;
public class Computer extends ElectronicProduct{ @Override public void open() { System.out.println("开启电脑"); super.setSTATE_OPEN(true); }
@Override public void close() { System.out.println("关闭电脑"); super.setSTATE_OPEN(false); }
public void useUSBDevice(USB usb){ usb.open(); usb.use(); usb.close(); } }
|
Mouse类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.tipdm3.Demo04;
public class Mouse extends ElectronicProduct{ public Mouse(String name) { super(name); }
public Mouse() { }
@Override public void usbFunction() { System.out.println("=============点击!============"); } }
|
KeyBoard类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.tipdm3.Demo04;
public class KeyBoard extends ElectronicProduct{ public KeyBoard() { }
public KeyBoard(String name) { super(name); }
@Override public void usbFunction() { System.out.println("==============打字!============"); } }
|
主类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package com.tipdm3.Demo04;
public class demo { public static void main(String[] args) { Computer computer = new Computer(); computer.open(); if(computer.isSTATE_OPEN()){
Mouse mouse = new Mouse("鼠标"); computer.useUSBDevice(mouse);
KeyBoard keyBoard = new KeyBoard("键盘"); computer.useUSBDevice(keyBoard); }else{ System.out.println("请先开启电脑,再使用USB设备!"); } computer.close(); }
}
|
1 2 3 4 5 6 7 8 9 10
| 开启电脑 打开鼠标
关闭鼠标 打开键盘
关闭键盘 关闭电脑
进程已结束,退出代码0
|