多态
简单入门
代码当中体现多态性,其实就是一句话: 父类引用指向子类对象。
格式:
父类名称对象名= new子类名称();
或者:
接口名称对象名= 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 static void main(String[] args) {
//使用多态的写法
//左侧父类的引用,指向了右侧子类的对象
//new的是谁用的就是谁 ,没有则向上找
Fu obj = new Zi();//子类方法
obj.method();
obj.methodFu();//父类特有方法
}
多态的正常写法,记忆与继承一样
访问成员变量的两种方式:
1.直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找
2.间接通过成员方法访问:看该方法属于谁,优先用谁,没有则向上找
public class Fu {
int num = 10;
public void showNum() {
System.out.println(num);
}
}
public class Zi extends Fu {
int num = 20;
int age = 16;
public void showNum() {
System.out.println(num);
}
}
/*
访问成员变量的两种方式:
1.直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找
2. 间接通过成员方法访问:看该方法属于谁,优先用谁,没有则向上找
*/
public static void main(String[] args) {
//使用多态的写法,父类引用指向子类对象
Fu obj = new Zi();
System.out.println(obj.num);
// obj.showNum();//子类没有覆盖重写,就是父: 10
obj.showNum(); //子类覆盖重写,就是子: 20
}
多态成员方法的访问规则
看new的是谁,就优先用谁,没有则向上找。
编译看左边,运行看右边。
public class Fu /*extends object*/ {
int num = 10;
public void showNum() {
System.out.println(num);
}
public void method() {
System.out.println("父类方法");
}
public class Zi extends Fu {
int num = 20;
int age = 16;
@Override
public void showNum() {
System.out.println(num);
@Override
public void method () {
System.out.println("子类方法");
}
public void methodZi () {
System.out.println("子类特有方法");
}
}
public static void main(String[] args) {
Fu obj = new Zi(); //多态
obj. method(); //父子都有,优先用子
obj. methodFu(); //子类没有,父类有,向上找到父类
}
成员变量成员方法对比
成员变量:编译看左边,运行还看左边。
成员方法。编译看左边,运行看右边。
多态的好处
个人理解:父类指向任意子类 通用一个方法
何意? 我只想要work方法 ,所有的教师 助教 都是我的员工
我就让 我的 “员工” work();
多态的转型
向上转型
向下转型
向上转型
1.对象的向上转型,其实就是多态写法:
格式:父类名称对象名= new子类名称0;
Animal animal = new Cat();
含义:右侧创建一 个子类对象,把它当做父类来看待使用。
创建了一只猫,当做动物看待,没问题。
注意事项:向上转型一定是安全的。
从小范围转向了大范围,从小范围的猫,向上转换成为更大范围的动物。
类似于:
double num = 100; //正确,int —> double, 自动类型转换。
public abstract class Animal {
public abstract void eat();
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
/*向上转型一定是安全的,没有问题的,正确的。
但是也有-一个弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
解决方案:用对象的向下转型[还原]*/
public static void main(String[] args) {
// 对象的向上转型,就是:父类引用指向之类对象。
Animal animal = new Cat();
animal.eat();//猫吃鱼
}
}
向下转型
对象的向下转型,其实是一个[还原]的动作。
格式:子类名称对象名= (子美名称)父类对象:
含义:将父类对象,[还原] 成为本来的子类对象。
Animal animal = new Cat0; //本来是猫,向上转型成为动物
Cat cat = (Cat) animal;本来是猫,已经被当做动物了,还原回来成为本来的猫
注竞事项:
a.必须保证对象本来创建的时候,就是猫,才能向下转型成为猫。
b.如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错。
public abstract class Animal {
public abstract void eat();
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catMouse() {
System.out.println("猫抓老鼠");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.print1n("狗吃SHIT");
public void watchHouse () {
System.out.print1n("狗看家");
}
}
}
public static void main(String[] args) {
// 对象的向上转型,就是:父类引用指向之类对象。
Animal animal = new Cat(); //本来创建的时候是一只猫
animal.eat(); //猫吃鱼
animal.catchMouse(); //错误写法!
//向下转型,进行“还原”动作
Cat cat = (Cat) animal;
cat.catchMouse(); //猫抓老鼠
//下面是错误的向下转型
//本来new的时候是一只猫,现在非要当做狗
//错误写法!编译不会报错,但是运行会出现异常:
// java. lang. ClassCastException,类转换异常
Dog dog = (Dog) animal;
}
如何才能知道一个父类引用的对象,本来是什么子类?
格式:
对象instance of 类名称
这将会得到一个boolean值结果, 也就是判断前面的对象能不能当做后面类型的实例。
public static void main(String[] args) {
Animal animal = new Dog(); //本来是一只狗
animal.eat(); //狗吃SHIT
//如果希望掉用子类特有方法,需要向下转型
//判断一下父类引用animal本来是不是Dog
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.watchHouse();
}
//判断一下animol本来是不是Cat
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.catchMouse();
}
giveMePet(dog)
}
//使用方法
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();
}
}
接口多态的综合案例
3.1笔记本电脑
笔记本电脑(laptop) 通常具备使用USB设备的功能。在生产时,笔记本都预留了可以插入USB设备的USB接口,
但具体是什么USB设备,笔记本厂商并不关心,只要符合USB规格的设备都可以。
定义USB接口,昊备最基本的开启功能和关闭功能。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守
USB规范,实现USB接口,否则鼠标和键盘的生产出来也无法使用。
3.2案例分析
进行描述笔记本类,实现笔记本使用USB鼠标、USB犍盘
●USB接口,包含打开设备功能、关闭设备叻能
●笔记本类,包含开机功能、关机功能、使用USB设备功能
●鼠标类,要实现USB接口,并具备点击的方法
●键盘类,要守现UsB接口, 且各敲击的方法
USB 接口类
public interface USB {
public abstract void open(); //打开设备
public abstract void close(); //关闭设备
}
computer电脑类
public class Computer {
public void power0n() {
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; //向下转型
mouse.click();
} else if (usb instsnceof Keyboard){ //先判断
Keyboard keyboard = (Keyboard) usb; //向下转型
keyboard.type();
}
usb.close();//关闭设备
}
}
Mouse类
//鼠标就是一 个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("鼠标点击);
}
}
Keyboard类
//键盘就是一 个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("健盘输入");
}
}
实现类
public static void main(String[] args) {
//首先创建-一个笔记本电脑
Computer computer = new Computer();
computer.power0n();
/*一般向上转型写法
准备一个鼠标,供电脑使用
Mouse, mouse = new Mouse();
Useb usbMouse = mouse
*/
//首先进行向上转型
USB usbMouse = new Mouse(); //.多态写法
//参数是usB类型,我正好传递进去的就是usB鼠标
computer.useDevice(usbMouse);
//创建一个USB键盘
Keyboard keyboard = new Keyboard(); //没有使用多态写法
//方法参数是USB类型,传递进去的是实现类对象
computer.useDevice(keyboard); /正确写法 !
computer.power0ff();
}