面向对象的三大特性之三——多态


typora-copy-images-to: images

什么是多态?

举例:

一般对象这样创建:

猫 x = new 猫();建立了猫的对象,并通过本类引用x指向了这个猫对象;

多态中的对象:

动物 x1 = new 猫();父类引用x1指向了子类这个猫对象;

x1这个引用即具备猫的形态,又具备着动物的形态。

简单的说:就是一个对象对应着不同类型,在代码中如何体现呢?父类或者接口的引用指向其子类的对象。

多态存在的三个前提:

  1. 要有继承关系
  2. 子类重写父类方法
  3. 父类引用指向子类对象

多态举例

父类Animal

class Animal {
    int num = 10;
    static int age = 20;

    public void eat() {
        System.out.println("动物吃饭");
    }
    public static void sleep(){
        System.out.println("动物睡觉");
    }
    public void run(){
        System.out.println("动物在奔跑");
    }
}

子类Cat

class Cat extends Animal{
    int num  = 66;
    static int age = 40;
    String name = "tomCat";

    public void eat() {
        System.out.println("猫吃饭");
    }

    public static void sleep(){
        System.out.println("猫睡觉");
    }

    public void catMouse(){
        System.out.println("猫在抓老鼠");
    }
}

测试类

/**
 * @ClassName: DuotaiDemo
 * @author: benjamin
 * @version: 1.0
 * @description: 多态举例
 */
public class DuotaiDemo {
    public static void main(String[] args) {

        // 父类引用指向了子类对象
        Animal am = new Cat();

        am.eat();
        am.sleep();
        am.run();

        System.out.println(am.num);
        System.out.println(am.age);
    }
}

结果

猫吃饭
动物睡觉
动物在奔跑
10
20

发现问题

子类重写了非静态成员方法eat(): 猫吃饭

子类重写了静态成员方法sleep(): 动物睡觉

子类未重写父类成员方法run():动物在奔跑

总结:

成员变量:编译看左边(父类),运行看左边(父类)

成员方法:编译看左边(父类),运行看右边(子类)

静态方法:不涉及对象的多态性。因为静态函数随着类的加载而加载。直接用类名调用即可。

特点举例

成员变量

简单地说:编译和运行都参考等号的左边

编译时:参考引用型变量所属的类中是否有调用的成员变量,有,编译通过,没有,编译失败;

运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。

举例:

执行DuotaiFu f = new DuotaiZi(); 此时子类型提升为父类型,用父类型找父

public class DuotaiDemo2 {
    public static void main(String[] args) {

        DuotaiFu f = new DuotaiZi();

        System.out.println(f.num);//3

    }

}
class DuotaiFu{
    int num = 3;
}

class DuotaiZi extends DuotaiFu{
    int num = 4;
}

内存图解

成员函数(重点)

非静态函数

简单说:编译时看左边,运行时看右边

编译时:参考引用变量所属的类中是否有调用的函数,有,编译通过,没有,编译失败;

运行时:参考的是对象所属的类中是否有调用的函数。

举例:

show函数运行时,持有this引用,指向了0x0034的对象(new Zi() ),找到该对象的show方法运行;

public class DuotaiDemo2 {
    public static void main(String[] args) {

        DuotaiFu f = new DuotaiZi();
        f.show();
    }
}
class DuotaiFu{

     void show(){
         System.out.println("fu show...");
     }
}

class DuotaiZi extends DuotaiFu{
    void show(){
        System.out.println("zi show...");
    }
}
// zi show...

内存图解:

静态函数

不涉及对象的多态性。因为静态函数随着类的加载而加载。直接用类名调用即可。

编译时:参考引用型变量所属的类中是否有调用的静态方法;

运行时:参考引用型变量所属的类中是否有调用的静态方法;

举例:

非静态方法必须绑定到指定的对象上,才能运行;

package java_demo_2;

public class DuotaiDemo2 {
    public static void main(String[] args) {

        DuotaiFu f = new DuotaiZi();
        f.method();
        DuotaiFu.method();
        DuotaiZi.method();

    }

}
class DuotaiFu{

     void show(){
         System.out.println("fu show...");
     }

     static void method(){
         System.out.println("父类静态方法");
     }
}

class DuotaiZi extends DuotaiFu{
    void show(){
        System.out.println("zi show...");
    }
    static void method(){
        System.out.println("子类静态方法");
    }
}

结果:

父类静态方法
父类静态方法
子类静态方法

向上转型和向下转型

向上转型:

  • 概念:Animal a = new Cat(); 猫提升成动物类型,但是猫特有的功能无法访问。
  • 目的:限制对特有功能的访问,专业讲就是向上转型。

向下转型:

  • 概念:如果还想用具体动物猫的特有功能,可以将对象进行向下转型。如:

    Cat c = (Cat) am;

    c.catchMouse();

  • 目的:为了使用子类中的特有方法。

举例:

// 向上转型
Animal am = new Cat();
am.eat();

// 向下转型
Cat cat = (Cat) am;
cat.catMouse();
System.out.println(cat.name);

输出
猫在抓老鼠
tomCat

类型转换异常:

对于转型,自始至终都是在类对象在做着类型的变化。猫-动物-猫

Cat c2 = (Cat) d;
c2.catchMouse();//ClassCastException
// 不能把一个猫——动物——狗;报错

类型判断:

instanceof :运行时指出对象是否是特定类的一个实例,只能用于引用数据类型判断,通常在向下转型前用于健壮性的判断。

举例:

public class DuotaiDemo {
    public static void main(String[] args) {
        //向上转型
        Animal c = new Cat();
        Animal d = new Dog();

        method(c);
        method(d);

    public static void method(Animal a){ 

        a.eat();
        if(a instanceof Cat){

            Cat c = (Cat) a;//向下转型,执行对象的特有方法;
            c.catchMouse();
        }
        else if(a instanceof Dog){
            Dog d = (Dog) a;
            d.lookHome();
        }
    }
}

参考链接

JAVA的多态用几句话能直观的解释一下吗? - 程序狗的回答 - 知乎
https://www.zhihu.com/question/30082151/answer/120520568

猜你喜欢

转载自www.cnblogs.com/benjieqiang/p/11481801.html
今日推荐