一、概述
代码当中体现多态性,其实就是一句话:父类引用指向子类对象。 格式: 父类名称 对象名 =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 class Demo01 {
public static void main(String[] args) {
//使用多态的写法
//左侧父类的引用,指向右侧子类的对象
Fu obj=new Zi();
obj.method();
obj.methodFu();
}
}
多态直白点就是左父右字。
二、多态中成员变量的使用特点:
访问成员变量的两种方式: 1、直接通过对象名称访问成员变量,看等号左边是谁,优先用谁,没有则向上找。 父类和子类分别定义一个成员变量10和20,测试类:
public static void main(String[] args) {
//使用多态的写法,父类的引用,指向右侧子类的对象
Fu obj=new Zi();
System.out.println(obj.num);//10
}
2、间接通过成员方法访问成员变量,该方法属于谁就用谁,没有则向上找。
在父类当中写方法:
public void showNum(){
System.out.println(num);
}
子类没有覆盖重写就是父类,子类覆盖重写就是子类
public static void main(String[] args) {
//使用多态的写法,父类的引用,指向右侧子类的对象
Fu obj=new Zi();
System.out.println(obj.num);//10
//子类没有覆盖重写就是父类,子类覆盖重写就是子类
obj.showNum();//20
}
三、多态中成员方法的使用特点:
在多态的代码当中,成员方法的访问规则是: 看new的是谁,就优先用谁,没有则向上找。 口决:编译看左边,运行看右边。
父类:
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("父类特有方法");
}
}
子类:
public class Zi extends Fu{
int num=20;
@Override
public void showNum() {
System.out.println(num);
}
@Override
public void method(){
System.out.println("子类方法");
}
public void methodZi(){
System.out.println("子类特有方法");
}
}
父类和子类有相同的成员方法method和特有的方法,测试类中的访问特点如下:
public static void main(String[] args) {
Fu obj=new Zi();//多态
obj.method();//父子都有,优先用子
obj.methodFu();//子类没有父类有,向上找父类
//编译看左,左边是Fu,Fu当中没有methodZi方法,所以编译报错
//obj.methodZi();//错误写法
}
对比一下: 成员变量:编译看左边,运行看右边。 成员方法:编译看左边,运行看右边。
四、向上转型:
对象的向上转型,其实就是多态的写法: 格式:父类的名称 对象名=new 子类的名称(); 含义:右侧创建一个子类的对象,把他当作父类来看待。 比如: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();
}
五、对象的向下转型:
向上转型一定是安全的,没有问题的,正确的,但是也有一个弊端: 对象一旦向上转型为父类,那么就无法调用子类特有的内容,比如猫抓老鼠。 解决方案: 用对象的向下转型还原。 2、对象的向下转型,其实就是一个(还原)的动作。 格式:子类名称 对象名=(子类名称)父类对象; 含义:将父类对象,[还原]成为本来的子类对象。 Animal animal=new Cat();//本来是猫,向上转型为动物 Cat cat=(Cat) animal;//本来是猫,已经被当作动物了,还原成为本来的猫 注意事项: a、必须保证对象本来创建的时候,就是猫,才能向下转型为猫 b、如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错。
public static void main(String[] args) {
Animal animal=new Cat();
animal.eat();
//向下转型
Cat cat=(Cat)animal;
cat.catchmouse();
//错误向下转型,animal原型是猫
Dog dog=(Dog)animal;//编译不报错,运行报错
}
六、笔记本USB接口案例:
创建USB接口:
public interface USB {
public abstract void open();//打开设备
public abstract void close();//关闭设备
}
创建键盘、鼠标继承USB:
//鼠标就是一个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("鼠标点击");
}
}
//键盘也是一个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 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;//向下转型
mouse.click();
}else if (usb instanceof KeyBoard){
KeyBoard keyBoard=(KeyBoard)usb;//向下转型
keyBoard.type();
}
usb.close();//关闭设备
}
}
进行测试:
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();
//方法参数是USB类型,传递进去的是实现类的对象
computer.useDevice(keyBoard);
computer.powerOff();
}
}