从零开始JAVA---多态

从零开始JAVA---多态,第1张

写在前面

想要理解JAVA中多态思想就必须先要搞清楚什么是:重写 (overide)

对比记忆学习

方法重载(overload):发生在同一个类中,定义了若干个方法名称相同参数列表不同的一组方法。


方法重写(overide):发生在有继承关系的类之间,子类定义了和父类除了权限不同,其他全都相同的方法,这样的一组方法称之为方法重写。
 

多态是建立在继承机制上的一种机制,具体点来说就是某个行为,当由不同的人去作时会产生出不同的效果。这就好比一台性能超强的Mac pro在大佬手里是一台能搞在极高分辨率下的影视后期、同时运行大量虚拟机、复杂精细的三维场景渲染、数百条音轨同步播放、高速处理极高分辨率的图片强大工具,性能好比一个小型工作站,而在咸鱼手里只是一个装逼的摆件,外加一个视频播放器。

总之多态是一种思想,是同一份源码,不同的传参/类调用会产生不同的效果。

向上转型

实际就是将父类的引用指向子类对象,当成父类对象来使用。

向上转型发生在有继承关系的类之间,不一定非要是子类,也可以是子类的子类。

父类名称 父类引用 = new 子类实例();

Animal animal = new Bird();

 

向上转型的最大意义在于参数统一化,降低使用者的使用难度。

public class Test {
    public static void main(String[] args) {
        // 2.作为类的使用者,程序的使用者
        // 没有向上转型,我要使用fun方法的话,我就得了解Animal以及其子类的所有对象
        // 我才能知道我到底调用的是谁
        fun(new Animal());
        fun(new Duck());
        fun(new Bird());
    }
    // 1.作为类的实现者
    // fun方法接收AnimaL以及其子类的对象作为参数
    // 假设现在没有向上转型,AnimaL有多少子类,我就得重载多少次fun方法
    // 大自然AnimaL动物子类有几百万种,就有几百万种子类,fun就得写上百万次!
    public static void fun(Animal animal) {}
    public static void fun(Duck duck) {}
    public static void fun(Bird bird) {}
}

        因为子类继承了父类,所有子类都有父类的属性,为了更简介的代码编程,为什么不能用父类指代所有子类?由此向上转型就产生了。

public class Test {
    public static void main(String[] args) {
        // 2.作为类的使用者,程序的使用者
        // 没有向上转型,我要使用fun方法的话,我就得了解Animal以及其子类的所有对象
        // 我才能知道我到底调用的是谁
        fun(new Animal());
        fun(new Duck());
        fun(new Bird());
    }
    // 只要是Animal及其子类,都是天然的Animal对象,都满足is a关系
    // 通过Animal最顶层的父类引用,指代所有的子类对象。
    public static void fun(Animal animal) {}
}

        fun()中animal 局部变量的引用调用 eat 方法时,当传入不同的对象时,表现出来了不同的 eat方法的行为,就是多态性。

        初学者初次接触多态时,总是纠结调用的是谁的方法,在这里很容易弄混,其实我们不用去看前半部分,看当前是通过哪个类new的对象,若该类重写了相关方法,则调用的一定是重写后的方法。千万不要被类名称搞晕,就看new的是谁,只要new的这个对象的类中覆写了同名方法,则调用的一定是覆写后的方法。

Bird 继承 Animal,Duck 继承 Bird,此时 Duck 中没有eat()方法,则会向上继承 “最近”的eat方法,也就是说会调用父类Bird的eat,而不是调用祖父类Animal的eat。

public class Animal {
    public void eat() {
        System.out.println("Animal类的eat方法");
    }
}
public class Duck extends Bird{
//    public void eat() {
//        System.out.println("Duck类的eat方法");
//    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Bird();
        Animal duck = new Duck();
        fun(duck);
    }
    public static void fun(Animal animal) {
        animal.eat();
    }
}

 

权限问题:当发生重写,必须要保证子类的权限大于等父类权限才可以重写。但是 private 修饰的父类方法不可以!!!子类压根都不可以使用,不可见,都不能继承!!!

 

能否重写static方法?
多态的本质就是因为调用了不同的子类“对象”,这些子类对象所属的类覆写相应的方法才能表现出不同的行为static和对象无关!!!!  方法重写只发生在普通方法中。

关于重写与构造方法的一道题

public class B {
    public B() {
        fun();
    }
    public void fun() {
        System.out.println("B.fun()");
    }
}
public class D extends B{

    private  int num = 10;

    public void fun() {
        System.out.println("D.fun,num = " + num);
    }

    public static void main(String[] args) {
        D d = new D();
    }
}

  正确答案: D

①程序从main进入开始,实例化一个对象D,调用类D,

②但是类D继承B,所以先执行构造方法B,此时又调用fun()方法,

③子类D重写了fun()方法,执行子类D中的fun(),

④因为没有执行 private int num = 10; ,所以num 等于整型默认值 0。

图解为:

 

 需要注意的问题,如果使用:引用名称.方法名称();

此时 引用名称 所在属的类中必须定义该方法,不然会报错,编译器会先在类中查找是否包含指定的方法。

 

 

发生向上转型的时机

方法传参(使用最多)

 向下转型

        我们将一个子类对象经过向上转型之后,我们就只能调用其父类的方法,再无法调用子类的方法,但有时候我们可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可。子类的引用 接收 被强制转为子类类型的父类引用指向的对象,这就是向下转型。

子类名称  子类引用 =  (子类名称)父类引用

Dog      dog  =  (Dog) animal;

 要发生向下转型,必须先发生向上转型。

 也就是说两个毫无相关的类之间无法强转。否者会报类型转换异常

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/794293.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存