目录
4.多态
4.1.多态概述
4.2.多态格式
- 代码当中体现多态性,其实就是一句话,父类引用指向子类对象。
- 格式:
- 父类名称 对象名称=new 子类名称();
- 接口名称 对象名=new 实现类名称();
package demo22.multi; public class Fu { public void method(){ System.out.println("这是父类method方法"); } public void methodFu(){ System.out.println("这是父类独有方法"); } } package demo22.multi; public class Zi extends Fu{ @Override public void method(){ System.out.println("这是子类method方法"); } } package demo22.multi; public class Demo01 { public static void main(String[] args) { //使用多态写法 Fu o=new Zi(); //左侧父类引用,指向右侧子类对象(猫是动物说法没问题) o.method(); //多态中方法访问特点:new谁就访问谁中的方法,没有则向上 o.methodFu(); } }
4.3.多态中成员变量访问特点
- 多态中成员变量的使用特点:和继承中一致,等号左侧是谁则就优先使用谁,没有则向上找
- 访问成员变量两种方法:
- 1.直接通过对象名称访问成员变量,看等号左边是谁则优先用谁,没有则向上找
- 2.间接通过成员方法访问成员变量,看该方法属于谁则优先用谁,没有则向上找
package demo23_multi; public class Fu { int num=10; public void showNum(){ System.out.println(num); } } package demo23_multi; public class Zi extends Fu { int num=20; int age=30; @Override public void showNum(){ System.out.println(num); } } package demo23_multi; public class Demo01 { public static void main(String[] args) { //使用多态写法,父类引用指向子类对象 Fu o=new Zi(); System.out.println(o.num);//优先到Fu类中访问num,10 //System.out.println(o.age);//优先到Fu类中找age,没有则向上找Object类中也没有 o.showNum();//20,方法属于等号右侧Zi中,没有则在向上找 } }
4.4.多态中成员方法访问特点
- 多态中成员方法使用特点:在多态代码中,成员方法的访问规则:看new的是谁,就优先访问谁,没有则向上找。
- 口诀:编译看左边,运行看右边。编译指将java代码编译成字节码文件
- 对比一下:
- 成员变量:编译看左边,运行还看左边
- 成员方法:编译看左侧,运行看右侧
4.5.多态好处
- 无论右边new的时候换成哪个子类对象,等号左边不需改变。
- 多态中成员方法访问特点:编译看左边,运行看右边,
- 即等号左边父类Employee中必须包含要调用的成员方法work()否则编译报错,另外运行work()方法是看等号右侧中work方法,没有则向上。我们现在唯一要做的就是调用work方法,其他不关系,在使用多态后只需要修改等号右侧子类对象便可调用不同的work方法,等号左侧是不需要修改。
package demo25_multi; public abstract class Employee { public abstract void work(); } package demo25_multi; public class Teacher extends Employee { @Override public void work() { System.out.println("讲课"); } } package demo25_multi; public class Student extends Employee { @Override public void work() { System.out.println("写作业"); } } package demo25_multi; public class Demo01 { public static void main(String[] args) { //若不用多态,只用子类,那么写法是 Teacher teacher = new Teacher(); teacher.work();//讲课 Student student = new Student(); student.work();//写作业 //现在唯一要做的事情就是调用work方法,其他功能不关心 //若使用多态写法: Employee teacher1=new Teacher(); teacher1.work(); Employee student1=new Student(); student1.work(); } }
4.6.对象向上向下转型
- 一.对象的向上转型,其实就是多态写法
- 格式:父类名称 对象名=new 子类名称(); Animal animal=new Cat();
- 含义:创建子类对象当做父类来看待使用。 创建一只猫,当做动物看待
- 注意事项:向上转型一定是安全的,从小范围的猫转向大范围动物。
- 弊端:对象向上转型一定是安全的,对象一旦向上转型为父类,就无法调用子类原本特有内容。创建一只猫对象,向上转型成父类动物对象,猫对象中的特有的捉老鼠方法就不能被访问(不是每个动物都会捉老鼠),
- 解决方法:用对象的向下转型(即还原)
2.二.对象的向下转型,其实就是一个【还原】的动作
- 格式:子类名称 对象名=(子类名称)父类对象
- 含义:将父类对象【还原】成为本来的子类对象
- Animal animal=new Cat();//本来是猫,向上转型成为动物
- Cat cat=(Cat)animal;//本来是猫,已经被当做动物了,现还原回来成本来的猫
- 注意事项:
- 1.必须保证对象本来创建的时候,就是猫,才能向下转型为猫
- 2.如果对象创建时候本来不是猫,现在非要向下转型成为猫,就会报错。
- 3.如何保证对象正常的向下转型:使用instanceof关键字。
*/
3.如何保证对象安全的上下转型--使用关键字instanceof
- 如何才能知道一个父类引用的对象,本来是什么子类(Cat/Dog)?
- 格式:对象 instanceof 类名称,这会返回一个布尔值,判断该对象是否是该类的实例
4.应用:
- 写一个送宠物的方法,什么宠物不一定,所以方法参数使用父类引用(对象向上转型), 这样任何子类对象(宠物)都可以传过来而方法参数不需要改动,这就是多态好处,父类下的任何子类对象都可以被接收到父类引用对象animal中,不需要频繁变动参数类型。这样向上转型的一个弊端就是无法访问子类独有方法,这就需要在使用的时候将对象向下转型
package demo26.multi; public abstract class Animal { public abstract void eat(); } package demo26.multi; public class Cat extends Animal{ @Override public void eat() { //重写父类抽象方法eat System.out.println("猫吃鱼"); } //子类特有方法 public void catchMouse(){ System.out.println("猫捉老鼠"); } } package demo26.multi; public class Dog extends Animal { @Override public void eat() {//重写父类抽象方法 System.out.println("狗吃骨头"); } //该子类特有的方法 public void watchHouse(){ System.out.println("狗看家"); } } package demo26.multi; public class Demo01 { public static void main(String[] args) { //对象的向上转型,就是,父类引用指向子类对象(也是多态写法) Animal animal=new Cat(); animal.eat();//猫吃鱼 //animal.catchMouse();错误写法,向上转型的对象无法访问子类特有方法,需向下转型 //向下转型,进行还原动作 Cat cat=(Cat)animal; cat.catchMouse(); //猫捉老鼠 缩写((Cat) animal).catchMouse(); //下面是错误的向下转型 //本来new的时候后是一只猫,现在非要转型成狗 //错误写法,编译不会报错,但是运行会出现异常java.lang.ClassCastException类转换异常 //Dog dog=(Dog)animal; } } package demo26.multi; public class Demo02 { public static void main(String[] args) { Animal animal=new Cat(); animal.eat(); //父类引用的对象只能访问共有的方法,也就是父类有的并在子类重写的 //如果希望调用子类特有方法,需要向下转型 //判断父类引用对象animal本来是不是属于子类Dog的实例 if (animal instanceof Dog){ //是则可以安全向下转型成Dog类对象 Dog dog=(Dog)animal; dog.watchHouse(); } if (animal instanceof Cat){ Cat cat = (Cat) animal; cat.catchMouse(); } } public static void giveMePet(Animal animal){ //判断父类引用对象animal本来是不是属于子类Dog的实例 if (animal instanceof Dog){ //是则可以安全向下转型成Dog类对象 Dog dog=(Dog)animal; dog.watchHouse(); } if (animal instanceof Cat){ Cat cat = (Cat) animal; cat.catchMouse(); } } }
4.7.多态练习
package demo27.multi;
//定义USB接口
public interface USB {
public abstract void open();//开启设备
public abstract void close();//关闭设备
}
package demo27.multi;
//鼠标是一个USB设备
public class Mouse implements USB {
@Override
public void open() {//重写父类抽象方法
System.out.println("打开鼠标");
}
@Override
public void close() {//重写父类抽象方法
System.out.println("关闭鼠标");
}
public void click(){ //子类独有方法
System.out.println("鼠标点击");
}
}
package demo27.multi;
//键盘是一个USB设备
public class Keyboard implements USB {
@Override
public void open() { System.out.println("打开键盘");}
@Override
public void close() { System.out.println("关闭键盘");}
public void type(){ System.out.println("敲键盘");//子类独有键盘 }
}
package demo27.multi;
//电脑类
public class Computer {
public void powerOn(){ System.out.println("开机"); }
public void powerOff(){ System.out.println("关机"); }
//电脑使用USB设备的方法,使用接口作为方法参数(多态),具体什么设备不知奥
public void usbDevice(USB usb){
usb.open();//打开usb设备
if (usb instanceof Mouse){//判断设备是鼠标,向下转型才能调用子类(鼠标)中独有方法
Mouse mouse=(Mouse)usb;
mouse.click();
}else if(usb instanceof Keyboard){
Keyboard keyboard = (Keyboard) usb;
keyboard.type();
}
usb.close();//关闭Usb设备
}
}
package demo27.multi;
public class Demo01 {
public static void main(String[] args) {
//创建电脑
Computer computer = new Computer();
computer.powerOn();//开机
//准备USB设备鼠标,供电脑使用
USB usbMouse=new Mouse();//对象向上转型
computer.usbDevice(usbMouse);//电脑使用鼠标设备;参数是USB类型,传递就是USB鼠标
computer.powerOff();
//准备USB设备键盘,共电脑使用
Keyboard keyboard = new Keyboard();
//方法参数是USB接口类型,传递进去的实现类对象(多态写法也是对象向上转型)
computer.usbDevice(keyboard);//发生了向上转型
computer.powerOff();
}
}