二十五、多态

1、概述

多态定义:多态是指同一对象,具有多个不同表现形式

举例:猫

我们可以说猫是猫:猫 cat = new 猫();

我们也可以说猫是动物:动物 animal = new 猫();

这个猫在不同的时刻表现出来了不同的形态,这就是多态

多态的前提【重点】:

  1. 继承或者实现(二选一)
  2. 方法的重写(意义体现:不重写,无意义)
  3. 父类引用指向子类对象(格式体现)

2、多态的成员访问

  1. 成员变量:编译看左边(父类),执行看左边(父类)
  2. 成员方法:编译看左边(父类),执行看右边(子类),如果执行了子类没有,往上找
  3. 构造方法:和继承一样,子类构造方法中会通过 super() 访问父类的构造

3、多态的优缺点

注意:

  1. 方法的参数是一个类,那么调用此方法需要传入此类的对象,或者传入此类的子类对象
  2. 方法的返回值类型是一个类的话,需要返回此类对象或者此类的子类对象

多态的好处:提高代码的扩展性,灵活性

多态的缺点:不能调用子类特有的功能

4、多态的使用方向

  1. 定义方法的时候,使用父类型作为参数,该方法就可以接受这父类的任意子类对象 !!!
  2. 定义方法的时候,使用父类型作为方法的返回值类型,该方法可以返回此父类任意子类对象!!!
  3. 定义变量时,用父类类型变量接收子类类型对象

5、多态的内存图

二十五、多态

6、多态的体现

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误; 如果有,则执行的是子类重写的方法;**③ **如果有,而子类没有重写,则执行的是父类的方法。

【定义父类】
public abstract class Animal{
    public abstract void eat();
}    

【定义子类】
public class Cat extends Animal{
    public void eat(){
        System.out.println("吃鱼");
    }
}    

【定义测试类】
public class Test{
    public static void main(String[] args) {
        // 多态形式,创建对象
        Animal a1 = new Cat();  
        // 调用的是 Cat 的 eat
        a1.eat();    
    }  
}    

多态在代码中的体现为:父类的引用指向子类对象

7、引用类型转换

多态的转型分为 向上转型向下转型

7.1 向上转型

定义:把子类的类型数据赋值给父类的类型变量,就是向上转型;这个过程是默认的。

使用格式: Animal a = new Cat();

7.2 向下转型

定义:把父类的类型数据赋值给子类的类型变量,就是向下转型;这个过程是强转的。

使用格式:Cat c = (Cat)a

7.3 为什么要转型

多态的缺点是不能调用子类特有功能,但是如果需要调用子类特有的功能,那么就需要向下转型

代码体现:

【定义类】
abstract class Animal {  
    abstract void eat();  
}  

class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void catchMouse() {  
        System.out.println("抓老鼠");  
    }  
}  

【定义测试类】
public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat(); 				// 调用的是 Cat 的 eat

        // 向下转型  
        Cat c = (Cat)a;       
        c.catchMouse(); 		// 调用的是 Cat 的 catchMouse
    }  
}    

7.4 转型异常

转型的过程中,一不小心就会遇到这样的问题,请看如下代码:

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        Dog d = (Dog)a;       
        d.watchHouse();        // 调用的是 Dog 的 watchHouse 【运行报错】
    }  
}

这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。这时需要使用 instanceof 了。

小结:类型转换异常,出现的原因:被转换的数据类型和实际数据类型不一致。

7.5 instanceof

引入:为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验

作用:判断一个对象是否属于一种引用数据类型

格式:

变量名 instanceof 数据类型 
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。

所以,在转换前,我们最好先做一个判断,代码如下:

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    }  
}
上一篇:Swift学习-Class


下一篇:python 创建类的语法