JAVA之Polymorphic(多态)

1.多态的几个必要条件

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

2.多态中类成员的变现情况

父类:

class Father{
    public int num = 10;

    public String print(){
        return "Father的print()方法!";
    }

    public static String staticprint(){
        return "Father的staticprint()方法";
    }
}

子类:

class Son extends Father{
    public int num = 20;

    public String print(){
        return "Son的print()方法";
    }

    public static String statocprint(){
       return "Son的staticprint()方法";
    }
}

测试类:

public class Main {
    public static void main(String[] args) {
        Father f = new Son();   //父类引用指向子类对象

        System.out.println("f的num值是:" + f.num);
        System.out.println("f的print()调用输出是:" + f.print());
        System.out.println("f的staticprint()调用输出是:" + f.staticprint());
    }
}

测试类输出结果:

f的num值是:10
f的print()调用输出是:Son的print()方法
f的staticprint()调用输出是:Father的staticprint()方法

这里面涉及到子类父类中的成员变量,成员方法,与静态方法的关系,一一进行解释。
成员变量:
在这里插入图片描述
可以看到在成员变量中,如果一个引用是Father类型的,那么他在指向堆中对象的时候只能看到Father对象中的变量情况(num = 10),看不到Son对象中的变量情况(num = 20),因此输出f.num的时候输出的时输出的就是Father类中的num值。

成员方法:
在这里插入图片描述
在成员方法之中,父类引用指向子类对象之后,要访问成员方法的时候,编译的时候对象指向的是父类的方法区,但是运行的时候指向的是子类的方法区域。因此输出结果的时候输出的是子类的方法结果,但是因为编译的时候会指向父类的方法区,因此如果父类中没有print()这一方法,则程序在编译过程中就会报错!

静态方法:
静态方法,即可以用类名进行引用的方法,显而易见的取决于你的引用类型,该程序中引用类型是Father,因此输出的结果肯定是父类Father中的静态方法,与Father.staticprint()的输出结果是一致的。

总而言之,成员变量,成员方法与静态方法在多态中编译时与运行时候的关系就是:
(Father f = new Son())
成员变量:编译看左边(Father),运行看左边(Father);
成员方法:编译看左边(Father),运行看右边(Son);
静态方法:编译看左边(Father),运行看左边(Father);

3.多态中的向上转型和向下转型

Father f = new Son();   //父类引用指向子类对象

父类引用指向子类对象就是向上转型,即将当前的概念提升为一个更宽泛的概念。
但是现在的f只能使用Father中有的方法,但是如果我们需要使用Son中特有的方法呢?
就需要向下转型:

Son s = (Son)f;

即将f专为一个更加具体的类型。
通过了解向下转型和向上转型,就会发现多态的一个弊端,即不能直接使用子类特有的方法,必须得向下转型。

4.多态的好处和弊端

弊端:不能使用子类特有的属性和行为。
好处:提高了代码的可维护性(继承保证)和可扩展性(多态保证)。
提高维护性是指因为继承的特性,使得我们只需要对父类进行修改就可以影响到继承于它的所有子类。
可扩展性:

public class Main {
    public static void main(String[] args) {
        method(new Cat());
        method(new Dog());
    }

    public static void method(Cat c){
        c.eat();
    }
}

class Animal{
    public void eat(){
        System.out.println("动物吃饭");
    }
}

class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }

    public void catchmouse(){
        System.out.println("抓老鼠");
    }
}


class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃肉");
    }

    public void lookhome(){
        System.out.println("看家");
    }
}

显然以上代码method(new Dog());这个语句是错误的,因为method()方法中传入的参数是Cat类型的,而这一个句子传入的参数是Dog类型的,很明显我们并不能说狗是猫,因此我们如果也想用这种静态方法的方式来调用Dog中的eat()方法,一种方式就是在重新写一个method()方法:

public static void method(Dog d){
        d.eat();
    }

但是这样看上去就会显得代码十分的多于重复,为了两个类型定义两种方法,那如果有很多种类型的对象,我们就需要定义许多十分相似的方法,这显然是不允许的,因此我们可以使用多态,因为Dog和Cat的父类都是Animal,因此我们可以只使用以下一个方法即可:

public static void method(Animal a){
        a.eat();
    }

其实就是这个使用了多态的这两条语句:

Animal a = new Cat();
Animal a = new Dog();

这显然是合理的,也是一种更简洁的做法。这也是多态在实际操作中最经常被运用的情况。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章