第二十四章 Polymorphism 多态
extends继承或者implements实现,是多态的前提。
一个对象拥有多种形态,这就是对象的多态性。
- 举例
小明是一个学生,同时也是一个人
小明是一个对象,
小明对象即是学生形态,也有人类形态。
24.1 多态的格式与使用
代码当中体现多态性,其实就是一句话:父类应用指向子类对象。
- 格式:
父类名称 对象名称 = new 子类名称();
or
接口名称 对象名称 = new 实现类名称();
public class Fu {
public void method() {
System.out.println("父类方法!")
}
public void methodFu() {
System.out.println("父类特有方法!")
}
}
public class Zi extends Fu {
@Override
public void method() {
System.out.println("子类方法!")
}
}
public class DemoMulti {
public static void main(String[] args) {
//使用多态的写法
//左侧父类的引用,指向了右侧子类的对象
Fu obj = new Zi();
obj.method();//子类方法!
obj.methodFu();
}
}
24.2 多态中成员变量的使用特点
访问成员变量的两种方式:
- 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
- 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
注意:成员变量不能覆盖重写,只有成员方法能重写。
public class Fu {
int num = 10;
public void showNum() {
System.out.println(num);
}
}
public class Zi extends Fu {
@Override
int num = 20;
int age = 30;
@Override
public void showNum() {
System.out.println(num);
}
}
public class DemoMultiField {
public static void main(String[] args) {
//使用多态的写法,父类引用指向子类对象
Fu ojb = new Zi();
System.out.println(ojb.num);//父10
// System.out.println(ojb.age);//错误写法
System.out.println("==================");
//子类没有覆盖重写,就是父10
//子类如果覆盖重写,就是子20
ojb.showNum();
}
}
24.3 多态中成员方法的使用特点
在多态的代码当中,成员方法的访问规则是:
看new的是谁,就优先用谁,没有则向上找。
- 口诀: 编译看左边,运行看右边。
- 成员变量:编译看左边,运行还看左边。
public class Fu {
public void method() {
System.out.println("父类方法");
}
public void methodFu() {
System.out.println("父类特有方法");
}
}
public class Zi extends Fu {
@Override
public void method() {
System.out.println("子类方法");
}
public void methodZi() {
System.out.println("子类特方法");
}
}
public class DemoMultiMethod {
public static void main(String[] args) {
Fu obj = new Zi();
obj.method();//优先用子
obj.methodFu();//子类没有,父类有,向上查找到父
//编译看左边,左边是Fu,Fu当中没有methodZi方法,所以编译报错。
// obj.methodZi();//错误
}
}
24.4 多态的好处
无论右边new的时候换成哪个子类对象,等号左边调用方法都不会变化。
- 提高了代码的维护性(继承保证);提高了代码的扩展性。
24.5 对象的向上转型
- 定义:其实就是多态的写法
- 格式:
父类名称 对象名称 = new 子类名称();
- 含义:右侧创建一个子类对象,把它当做父类看待使用。
- 举例:
public abstract class Animal {
public abstract void eat();
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
public class Demo01Main {
public static viod mian(String[] args) {
Animal animal = new Cat();
animal.eat();
}
}
- 注意事项:
- 向上转型一定是安全的,因为从小范围转向了大范围。
- 对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
24.6 对象的向下转型
- 定义:其实就是一个**【还原】**的动作
- 格式:
子类名称 对象名 = (子类名称) 父类对象;
- 含义:将父类对象,【还原】成为本来的子类对象。
- 举例:
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public void catchHouse() {
System.out.println("狗吃看家");
}
}
public class Demo02Main {
public static viod mian(String[] args) {
Animal animal = new Cat();
// animal.catchMouse;//错误写法
//向下转型
Cat cat = (Cat) Animal;
cat.catchMouse();
//错误的向下转型
//本来new的是一只猫,现在非要当成狗
// Dog dog = (Dog) animal; //可以编译,但是运行报错
}
}
- 注意事项:
a.必须保证对象本来创建的时候,就是猫,才能向下转型成为猫。
b.如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错。
java.lang.ClassCastException
类转换异常
其实类似于:基本类型中的强制类型转换
int num1 = (int) 10.0;
int num2 = (int) 10.5; //不可以,精度损失。
24.7 instanceof 关键字进行类型判断
如何才能知道一个父类引用对象,本来是什么子类?
格式:
对象 instanceof 类名称
//这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。
//参考24.5-24.6
public class DemoInstanceof {
public static void main(String[] args) {
Animal animal = new Dog();
giveMeAPat(new Dog());
}
public static void giveMeAPat(Animal animal) {
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.watchHouse();
}
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
Cat.catchMouse();
}
}
}
24.8 笔记本USB 接口案例
public abstract class USB {
public abstract void open();
public abstract void close();
}
public class Computer {
public void powerOn() {
System.out.println("开机");
}
public void powerOff() {
System.out.println("关机");
}
//使用USB设备的方法,使用接口作为方法的参数
public void useDevice(USB usb) {
usb.open;
if (usb instanceof Mouse) {
Mouse mouse = (Mouse) usb;
} else if (usb instanceof Keyboard) {
Keyboard keyborad = (Keyboard) usb;
}
usb.close;
}
}
public class Mouse implement USB {
@Override
public void open() {
System.out.println("打开鼠标");
}
@Override
public void close(){
System.out.println("关闭鼠标");
}
public void press(){
System.out.println("点击鼠标");
}
}
public class Keyboard implement USB {
@Override
public void open() {
System.out.println("打开键盘");
}
@Override
public void close(){
System.out.println("关闭键盘");
}
public void type(){
System.out.println("输入文字");
}
}
public class DemoMain {
public static void main(String[] args) {
Computer computer = new Computer();
computer.poweron();
USB usbMouse = new Mouse();//多态写法
computer.useDevice(usbMouse)
Keyboard keyboard = new Keyboard();//没有使用多态写法
computer.useDevice(Keyboard);//发生了向上转型
// computer.useDevice(new Keyboard());//同上
computer.poweroff();
}
}