【Java】多态

本文详细解释了多态的概念,介绍了在Java中实现多态的条件,包括继承、重写和通过父类引用调用方法。文章还通过实例展示了向上转型和向下转型的区别,以及多态的优缺点,如降低代码复杂性和可拓展性,但存在属性和构造方法多态性的局限性。
摘要由CSDN通过智能技术生成

1.什么是多态?

        多态,通俗来讲,就是多种状态。具体来说就是当不同的对象去完成某种行为时会产生不同的状态。比如猫和狗叫时会发出不同的声音;黑白打印机和彩色打印机打印出的颜色不同...

        总的来说就是:同一件事发生在不同对象身上就会产生不同的结果。

2.多态的实现条件

        Java中要实现多态必须满足以下条件,缺一不可:

        1.必须在继承的体系下

        2.子类必须对父类的方法进行重写

        3.通过父类的引用调用重写的方法

多态的体现:当代码运行时,当传递不同的类对象时,会调用对应类中的方法。

举例如下:

public class Animal {
    String name;
    int age;

    public Animal(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void eat(){
        System.out.println(name+"在吃饭");
    }
}


public class Cat extends Animal{    //继承Animal父类
    public Cat(String name,int age){
       super(name,age);
    }
    @Override
    public void eat(){    //对父类方法进行重写
        System.out.println(name+"吃鱼");
    }
}


public class Dog extends Animal{
    public Dog(String name,int age){
        super(name,age);
    }
    @Override
    public void eat(){
        System.out.println(name+"吃骨头");
    }
}


public class TestAnimal {
//编译器在编译代码时,并不知道是调用Dog还是Cat中的eat方法
//当程序运行起来后,形参a引用的具体对象确定时,才能调用对应方法
//注意:此时的形参类型必须是父类类型才可以
    public static void eat(Animal a){
        a.eat();
    }

    public static void main(String[] args) {
        Cat cat=new Cat("卷卷",2);
        Dog dog=new Dog("咕咕",3);
        eat(cat);
        eat(dog);

//上述代码是类的实现者编写的

        执行结果如下:以下代码是类的调用者编写的。

3.重写(Override)

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

        重写的好处在于,子类可以根据自己的需求,定义特定属于自己的行为。即子类可以根据需要实现父类的方法。

方法重写的规则如下:

1.子类再重写父类方法时,一般必须与父类原型保持一致:返回值类型、方法名、(参数列表)要完全一致。

2.被重写的方法返回值类型可以不同,但必须是具有父子关系的。

3.子类访问权限不能比父类中被重写的方法访问权限低。比如:父类方法被public修饰,子类中重写该方法就不能声明为protected。

4.父类被static、private修饰的方法、构造方法不能被重写。

5.重写的方法可以用@Override注解来显式指定。这个注解可以帮助我们进行一些合法性检验。

4.向上转型和向下转型

4.1向上转型

        向上转型就是创建一个子类,将它当作父类对象来使用。

语法格式:父类类型 对象名=new 子类类型()

Animal animal=new Cat("卷卷",2);

        Animal时父类类型,但可以引用一个子类对象,原因是从小范围向大范围的转换。

猫和狗都是动物,因此将子类对象转化为父类引用是合理的。大范围可以囊括小范围。 

        使用场景:方法传参、做返回值、直接赋值。

public class TestAnimal {
//方法传参:形参为父类型引用,可以接受任意子类的对象
    public static void eat(Animal a){
        a.eat();
    }
//做返回值:返回任意子类对象
    public static Animal buyAnimal(String var){
        if("狗".equals(var)){
            return new Dog("修狗",1);
        }
        else if ("猫".equals(var)){
            return new Cat("猫咪",1);
        }
        else {
            return null;
        }
    }

    public static void main(String[] args) {
        Animal cat=new Cat("卷卷",2);  //直接赋值:子类对象赋值给父类对象
        Dog dog=new Dog("咕咕",3);
        eat(cat);
        eat(dog);

        Animal animal=buyAnimal("狗");
        animal.eat();

        animal=buyAnimal("猫");
        animal.eat();
    }
}

【向上转型优缺点】

优点:让代码实现更加灵活简单。

缺点:不能调用子类特有的方法。

4.2向下转型

        将一个子类对象经过向上转型后当成父类方法使用,就无法调用子类中特有的方法,但当恰恰需要这些子类特有方法时,这是将父类引用在还原成子类对象即可,即向下转型。

public class TestAnl {
    public static void main(String[] args) {
        Cat cat=new Cat("小米",2);
        Dog dog=new Dog("小七",1);

        //向上转型
        Animal animal=cat;
        animal.eat();
        animal=dog;
        animal.eat();//编译失败,编译器将animal当成Animal对象处理
        //但是Animal类中没有bark方法

        cat=(Cat)animal;//向上转型,程序可通过编译但抛出异常
        //animal实际指向是狗,现在要强制还原为猫,无法正常还原
        cat.mew();

        //animal本来指向就是狗,因此将animal还原成狗是安全的
        dog=(Dog)animal;
        dog.bark();
    }
}

向下转型用的比较少也不安全,为了提高向下转型的安全性,引入了instanceof,如果该表达式为true,则可以安全转换。

public class Testanl2 {
    public static void main(String[] args) {
        Cat cat=new Cat("小米",2);
        Dog dog=new Dog("小七",1);

        //向上转型
        Animal animal=cat;
        animal.eat();
        animal=dog;
        animal.eat();

        if(animal instanceof Cat){
            cat=(Cat)animal;
            cat.mew(); 
        }

        if(animal instanceof Dog){
            dog=(Dog) animal;
            dog.bark();
        }
    }
}

5.多态的优缺点

【优点】

       1. 能够降低代码的“圈复杂度”(代码中条件语句、循环语句出现的次数),避免大量使用if-else;

        2.可拓展能力更强,想要增加新的子类对象直接New一个新类就行,不用再原代码基础上添加if-else改动太多很不方便且成本高。

【缺点】

        1.属性没有多态性,当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性。

        2.构造方法没有多态性。

  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值