JAVA中的多态

一、向上转型
含义:父类的一个引用,指向子类。

class Person {
    public String name;

    public Person(String name) {
        this.name = name;
    }

    public static void age(int age) {
        System.out.println(age);
    }
}
class Dad extends Person {
    public Dad(String name) {
        super(name);
    }

    public static void main(String[] args) {
        Dad dad = new Dad("父亲");
        Dad.age(36);
    }
}

在上述继承中,main 函数中可以有其他的实例引用方法。

 //第一种写法
 Dad dad = new Dad("父亲");
 Person dad1 = dad;
 
 //第二种写法
 Person dad1 = new Dad("父亲");

这两种写法都属于向上转型,属于直接赋值。
还有方法传参、方法返回时也可以使用,使用方法相同。
方法传参:

Dad.age(36);//上述代码中
// =>
Person.age(36);

方法返回:

public static void main(String[] args) {
    Person person = findPerson();
}
public static Person findPerson() {
    Dad dad = new Dad("父亲");
    return dad;
}

此时方法 findPerson 返回的是一个 Person 类型的引用, 但是实际上对应到 Dad 的实例。

二、向下转型
向上转型是子类对象转父类对象,向下转型则是父类对象转子类对象。
向上转型的缺点:

class Person {
    protected String name;

    public Person(String name) {
        this.name = name;
    }

    protected void age(int age) {
        System.out.println(this.name + "的年龄是" + age);
        System.out.println(age);
    }

    public static void main(String[] args) {
        Person person = new Son("儿子");
        person.age(18);
        //person.subject("数学");
    }
}

class Son extends Person {
    public Son(String name) {
        super(name);
    }

    protected void age(int age) {
        System.out.println(this.name + "的年龄是" + age);
        System.out.println(age);
    }

    public void subject(String subject) {
        System.out.println(subject);
    }
}

结果正常:
在这里插入图片描述
但如果调用 person.subject("数学");后,编译出错:
在这里插入图片描述
可见:
1.编译器检查有哪些方法存在, 看的是 Person 这个类型
2.执行时究竟执行父类的方法还是子类的方法, 看的是 Son 这个类型.

要弥补上述代码的不足,就需要向下转型。

public static void main(String[] args) {
        Person person = new Son("儿子");
        Son son = (Son) person;
        son.age(18);
        son.subject("数学");
    }

此时,代码可正常运行:
在这里插入图片描述
但也容易出错,例如:

public static void main(String[] args) {
        Person person = new Dad("儿子");
        Son son = (Son) person;
        son.age(18);
        son.subject("数学");
    }

会出现异常:
Exception in thread "main" java.lang.ClassCastException: Inherit.Dad cannot be cast to Inherit.Son
为避免这种问题,需要先判断能否转换。
可以写成:

    public static void main(String[] args) {
        Person person = new Son("儿子");
        if(person instanceof Son) {
            Son son = (Son) person;
            son.age(18);
            son.subject("数学");
        }
    }

三、动态绑定
对向上转型的代码稍做改动:

class Person {
    protected String name;

    public Person(String name) {
        this.name = name;
    }

    public void age(int age) {
        System.out.println(this.name + "的年龄是" + age);
        System.out.println(age);
    }
}
class Dad extends Person {
    public Dad(String name) {
        super(name);
    }

    public void age(int age) {
        System.out.println(this.name + "的年龄是" + age);
        System.out.println(age);
    }

    public static void main(String[] args) {
        Person person1 = new Person("父亲");
        person1.age(36);
        Person person2 = new Dad("爹");
        person2.age(42);
    }
}

输出结果:
在这里插入图片描述
由此例可总结:
1.person1 指向 Person 类型的实例, person2 指向 Dad 类型的实例。
2. person1.age() 实际调用了父类的方法, 而 personl2.age() 实际调用了子类的方法。
可见, 在 Java 中调用某个类的方法, 究竟执行父类方法的代码还是子类方法的代码, 要看这个引用指向的是父类对象还是子类对象。这个过程是程序运行时决定的(而不是编译期), 因此称为 动态绑定。

四、方法重写
上述代码,子类实现父类的同名方法, 并且参数的类型和个数完全相同, 这种情况称为 覆写/重写/覆盖(Override).
注意事项:
1.与重载区分开
2.普通方法可以重写, static 修饰的静态方法不能重写
3.重写中子类的方法的访问权限不能低于父类的方法访问权限(public > protected > private).
4.重写的方法返回值类型不一定和父类的方法相同(建议写成相同, 特殊情况除外).
5.建议在代码中进行重写方法时显式加上 @Override 注解(能进行合法性校验).(alt + insert)

区别重载和重写:
在这里插入图片描述
五、多态
将向上转型、向下转型、动态绑定、方法重写综合运用到一个代码中,就是多态了。
简单来说,就是“一个引用,就能表现出多种不同形态”。
优点:
1.多态可以理解成是封装的更进一步,使类调用者对类的使用成本进一步降低:
a.封装是让类的调用者不需要知道类的实现细节.
b.多态能让类的调用者连这个类的类型是什么都不必知道, 只需要知道这个对象具有某个方法即可.
2.能够降低代码的 “圈复杂度”, 避免使用大量的 if - else.
3. 可扩展能力更强:
只需要创造一个新的实例就可以,不需要用 if - else 进行修改.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值