第七章_Java中面向对的的三大特征之多态
1.什么是多态?
指同一个对象在不同时刻表现出来不同的形态。
2.多态的前提
- 要有继承或实现(接口)关系
- 要有方法的重写
- 要有父类引用指向子类对象 --> 父类 对象名= new 子类()
代码演示:
public class Test {
public static void main(String[] args) {
//原始方式调用,当前的事物是一只猫
Cat cat = new Cat();
cat.eat();
cat.catchMouse();
System.out.println("--------------------");
//多态形式调用,当前代表的是一个动物,并不特指猫
Animal animal = new Cat();
animal.eat();
// animal.catchMouse();//不能调用子类中的特有方法
}
}
class Animal{
public void eat(){
System.out.println("动物都吃饭");
}
}
class Cat extends Animal{
@Override
public void eat() {//重写父类中的eat方法
System.out.println("猫吃鱼");
}
public void catchMouse(){//子类中特有的方法
System.out.println("猫抓老鼠");
}
}
多态不可以调用子类的特有方法,编译无法通过
把这行代码注释后的执行效果
3.多态的成员访问特点
成员访问特点
3.1成员变量
编译看父类,运行看父类
看等号左边是谁,先调用谁
3.2成员方法
编译看父类,运行看子类
看new的是谁,先调用谁.子类没有,找父类
代码演示:
public class Test {
public static void main(String[] args) {
Animal animal = new Cat();
animal.eat();//猫吃鱼
animal.drink();//动物都喝水
String name1 = animal.name;
System.out.println(name1);//Animal
System.out.println("---------------");
Cat cat = new Cat();
cat.eat();//猫吃鱼
//子类中并没有重写drink方法,子类没有就找父类
cat.drink();//动物都喝水
String name2 = cat.name;
System.out.println(name2);//Tom
}
}
class Animal{
String name = "Animal";
public void eat(){
System.out.println("动物都吃饭");
}
public void drink(){//此方法子类中没有重写
System.out.println("动物都喝水");
}
}
class Cat extends Animal{
String name = "Tom";
@Override
public void eat() {//重写父类中的eat方法
System.out.println("猫吃鱼");
}
public void catchMouse(){//子类中特有的方法
System.out.println("猫抓老鼠");
}
}
执行效果:
总结
1.多态中成员变量需要看"="左边,左边是谁就调用谁
2.多态中成员方法需要看"="右边,右边是谁先调用谁,如果子类没有就找父类的
4.多态的优缺点
4.1优点(方法的参数传递)
定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作。
提高程序的扩展性。
4.2缺点
不能直接使用子类的特有成员 --> 多态最大的缺点
4.3原始方法的优缺点
优点:既可以调用自己特有的,还能调用重写的,还能调用继承的
缺点:扩展性差
5.多态中的转型
5.1向上转型(默认)
父类引用指向子类对象,一般的多态形式就是向上转型。
弊端:不能直接调用子类特有方法
5.2向下转型
格式:子类型 对象名 = (子类型)父类引用; -->向下转型后可以使用子类中特有的方法
简单举例:
double b = 10;
int i = b;–>报错
强转–>int i = (int)b
代码演示:
public class Test {
public static void main(String[] args) {
//向下转型格式:
// 子类型 对象名 = (子类型)父类引用;
Animal animal = new Cat();
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
class Animal{
public void eat(){
System.out.println("动物都吃饭");
}
}
class Cat extends Animal{
@Override
public void eat() {//重写父类中的eat方法
System.out.println("猫吃鱼");
}
public void catchMouse(){//子类中特有的方法
System.out.println("猫抓老鼠");
}
}
执行效果
5.3多态中转型存在的风险和解决方案
风险
如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException 的错误
解决方案
-
关键字
instanceof
-
使用格式
变量名 instanceof 类型
通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
代码演示:
public class Test {
public static void main(String[] args) {
useAnimal(new Dog());// 相当于Animal animal = new Dog();
System.out.println("----------------");
useAnimal(new Cat());// 相当于Animal animal = new Cat();
}
//定义一个使用动物的方法
public static void useAnimal(Animal animal){
/*
使用多态的形式调用动物的eat方法
如果参数是dog就调用dog中的eat方法
如果参数是cat就调用cat中的eat方法
*/
animal.eat();
//如果参数是此处就会出现类型转换异常的错误ClassCastException
/*Dog dog = (Dog) animal;
dog.watchHome();*/
if (animal instanceof Dog){
Dog dog = (Dog) animal;
dog.watchHome();
}else if (animal instanceof Cat){
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
}
abstract class Animal {
public abstract void eat();
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃肉");
}
public void watchHome(){
System.out.println("看家");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
执行效果: