多态
什么是多态
在继承父类或者实现接口的基础上,允许同一类事物出现不同的状态
多态的前提:继承或实现的关系、方法的重写、父类(接口)引用指向子类(实现类)对象
表现形式
父类 变量 = 子类对象();
接口 变量 = 实现对象();
需求:
- 定义Animal动物类作为父类,规定吃饭、喝水功能。
- 定义子类Dog和Cat,分别创建Dog对象和Cat对象,调用吃饭功能和喝水功能
思考:
1.定义Animal动物类,作为父类
2.定义Dog狗类和Cat猫类,作为子类
3.分别创建Dog和Cat对象,调用吃饭、喝水功能
/*** 动物类,作为父类的*/
public abstract class Animal {//喝水public void drink() {System.out.println("喝水");}//吃饭public abstract void eat();
}
/*** 猫类*/
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}
}
/*** 狗类,作为子类*/
public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗吃肉");}
}
之前的想法:
Dog dog = new Dog();
Cat cat = new Cat();
引入多态的思想:
//允许将子类对象,给父类类型变量赋值
//将dog和cat变量变成同一类型
Animal dog = new Dog();
Animal cat = new Cat();//呈现相同状态
dog.drink();
cat.drink();
//呈现不同状态
dog.eat();
cat.eat();
多态关系中,成员的访问特点
目标:了解多态中成员的访问特点
- 方法调用:编译看左边,运行看右边
- 变量调用:编译看左边,运行也看左边
需求:有父类Fu和子类Zi,请使用多态的形式创建对象并访问各自属性和方法
//父类
public class Fu {String field = "父类属性";public void method() {System.out.println("父类方法");}
}//子类
public class Zi extends Fu {String field = "子类属性";String ziField = "子类特有属性";public void method() {System.out.println("子类方法");}public void ziMethod() {System.out.println("子类特有方法");}
}
public static void main(String[] args) {/*** 多态中成员访问特点:* 变量调用:编译看左边,运行也看左边* 方法调用:编译看左边,运行看右边** 需求:有父类Fu和子类Zi,请使用多态的形式创建对象并访问各自属性和方法*///1.用多态的代码形式创建Zi对象,给Fu类型变量赋值Fu zi = new Zi();//2.访问父类和子类都有(同名)的属性System.out.println(zi.field);//结果: 父类属性//3.访问父类没有但子类有的属性//System.out.println(zi.ziField);//报错//访问变量:编译看左边,运行也看左边System.out.println("-------------------");//4.访问父类和子类都有(同名)的方法zi.method();//结果: 子类方法//5.访问父类没有但子类有的方法//zi.ziMethod();//报错//访问方法:编译看左边,运行看右边}
多态好处与弊端
优势:解耦合,提高方法的扩展性,把方法的形参写成父类/接口类型,调用方法的时候可以传递子类/实现类对象
劣势:多态下不能使用子类的特有功能
需求:利用多态技术优化useDog和useCat方法,使两个方法变为一个方法!
public abstract class Animal {public void drink() {System.out.println("喝水!");}public abstract void eat();
}
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}//猫类特有功能:抓老鼠public void catchMouse() {System.out.println("猫抓老鼠");}
}
public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗吃肉");}//狗类特有功能:狗看家public void lookHome() {System.out.println("狗看家");}
}
public static void main(String[] args) {feedAnimal(new Dog());feedAnimal(new Cat());
}public static void feedAnimal(Animal animal) {animal.eat();//2.尝试访问子类的特有功能,失败报错//访问:狗看家//animal.lookHome();//访问:猫抓老鼠//animal.catchMouse();//多态的弊端:在多态形式下,不能访问子类的特有功能}
多态的转型
目标:了解多态下引用数据类型的类型转换操作
多态转型指的是:把父类类型强制转换为子类类型
格式:子类 变量 = (子类)被转换的数据;
原本是什么类型,才能还原为什么类型
Animal a = new Dog();
Dog d = (Dog)a;
instanceof关键字
作用:测试它左边的对象是否是它右边的类的实例
if( a instanceof Dog ){Dog d = (Dog)a;d.lookHome();}
目标:了解多态下引用数据类型的类型转换操作
public static void useAnimal(Animal animal) {animal.eat();//1.强转成Dog狗类型//Dog dog = (Dog) animal;//调用狗的特有功能//dog.lookHome();//2.正确的强转方案:先判断,后强转。使用instanceofif (animal instanceof Dog) {Dog dog = (Dog) animal;dog.lookHome();}//3.在高版本的jdk中,上面的代码可以进一步简化if (animal instanceof Cat cat) {cat.catchMouse();}}
小结
- 多态的形式有表现形式有两种
父类变量接收__子类对象
接口变量接收__实现类对象 - 多态的好处是什么?
如果方法的参数是父类类型,那么调用方法可以传递子类对象
如果方法的参数是接口类型,那么调用方法可以传递实现类对象______ - 多态的弊端是什么?
在多态的情况下,不能调用子类或者实现类的_特有方法