【Java】多态(精简版)

本博客将结合《Java核心技术 卷一》以及博主本人知识,为大家介绍Java面向对象程序设计的基本概念——多态。希望能帮助大家更轻松地学习多态。

一.什么是多态

多态,指为不同数据类型的实体提供统一的接口。多态类型,可以将自身所支持的操作套用到其它类型的值上。——百度百科

多态是对象变量的一种状态,使一个类型的变量可以引用父类的对象,也可以引用父类的任何一个子类对象。

简单来讲,就是对象引用具有多种状态。

为了理解这一概念,请看以下代码:

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

Animal类型的引用变量cc的引用对象可以是Animal类,也可以是Cat、Dog类,这样cc这个类的引用变量就可以是这其中任意一种状态。

二.实现多态

1.实现多态的条件

实现多态,必须满足以下三项条件:

(1) 必须在继承体系下,

要在继承体系下,是因为只有在该体系下,才能进行类型的转型。

(2)子类必须要对父类中方法进行重写

子类要重写父类方法,只有重写方法,才能提供不同的行为,实现多态。

(3)通过父类的引用调用重写的方法(向上转型)

将子类对象的地址赋值给父类类型的引用,然后通过这个父类类型的引用调用重写的函数。在运行时,程序会根据实际指向的对象类型来决定调用哪个版本的函数,这被称为动态绑定或后期绑定。

2.重写父类方法

重写(override),也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程 进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

例如,以下代码:

class Dog{
    ...
    public void bark(){
        System.out.println("wolf!");
    }
    ...
}



class Husky extends Dog{
    ...
    @override
    public void bark(){
        System.out.println("wowu!");
    }
    ...
}


public class test {
    public static void main(String[] args) {
        Dog cc = new Husky()   
        cc.bark();
    }
}

如上就是一个简单的重写,让编译器根据cc所指向的实际对象来调用相应的方法,这就是多态的一个简单应用。

ps:重写的方法, 可以使用 @Override 注解来显式指定,有了这个注解能帮我们进行一些合法性校验.。例如不小心 将方法名字拼写错了 (比如写成brak), 那么此时编译器就会发现父类中没有 brak 方法, 就会编译报错, 提示无法构成重写。

ps:注意区分重载(overload)与重写(override),前者参数不同,返回类型可以不同,后者参数要相同,返回类型也要相同,访问限制符不能更私有。

3.向上转移和向下转型

(1)向上转型

字面理解即可,即以子类对象指向父类类型:

父类类型 对象名 = new 子类类型()

Animal cc = new Dog(); 

向上转型的优点:让代码实现更简单灵活。如以下代码:

// 父类:动物
class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

// 子类:猫
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
    public void catchMouse(){
    ......
    }
}

// 子类:狗
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

public class Test {
    public static void main(String[] args) {
        // 向上转型示例
        Animal animal1 = new Cat();  // Cat向上转型为Animal
        Animal animal2 = new Dog();  // Dog向上转型为Animal
        
        // 统一处理不同类型的动物
        animalDoSomething(animal1);
        animalDoSomething(animal2);
    }

    // 可以接收任何Animal及其子类的对象
    private static void animalDoSomething(Animal animal) {
        animal.makeSound();  // 运行时多态,自动调用实际类型的实现
    }
}

这里的animalDoSomething()方法统一接收了Dog和Cat两个不同类的变量,让代码更加灵活,同时保证了代码的可扩展性。

向上转型的缺陷:不能调用到子类特有的方法。如上的animalDoSomething()方法就不能调用catchMouse()的方法。这是为了安全,防止cat类调用引发异常。向下转型就是为了解决这一缺陷而存在的。

(2)向下转型

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的 方法,此时:将父类引用再还原为子类对象即可,即向下转换。如下代码就是说明向下转型的应用场景的:

// 父类:动物
class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

// 子类:猫(新增特有方法)
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
    
    // 猫的特有方法
    public void purr() {
        System.out.println("呼噜呼噜...");
    }
}

// 子类:狗(新增特有方法)
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
    
    // 狗的特有方法
    public void fetch() {
        System.out.println("捡回飞盘");
    }
}

public class Test {
    public static void main(String[] args) {
        // 创建混合动物集合(向上转型)
        Animal[] animals = {
            new Cat(),
            new Dog(),
            new Cat()
        };

        // 处理动物集合
        for (Animal animal : animals) {
            animal.makeSound();  // 公共方法直接调用
            
            // 向下转型检查(使用instanceof)
            if (animal instanceof Cat) {
                Cat cat = (Cat) animal;  // 显式向下转型
                cat.purr();             // 调用猫的特有方法
            } else if (animal instanceof Dog) {
                Dog dog = (Dog) animal;  // 显式向下转型
                dog.fetch();            // 调用狗的特有方法
            }
        }
    }
}

instanceof关键字:用于测试一个对象是否是指定类型或其子类型的实例。它返回一个布尔值,如果对象是指定类型(或者其子类型)的实例,则返回 true;否则返回 false

说明:向下转型用的比较少,而且不安全,万一转换失败,如cat调用dog特有方法,运行时就会抛异常。Java中为了提高向下转型的安全性,引入 了instanceof,如果该表达式为true,则可以安全转换。

结语

以上就是本次分享,想要深入学习面向对象,还得多多写代码,自己体验才行,写着写着说不定自己就懂了。好了,下次将介绍抽象类和接口,欢迎关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值