Java 面向对象中的多态

本文详细解析了多态的原理,包括向上转型、动态绑定,通过Shape、Circle、Rect和Triangle类实例展示多态如何减少if-else并提升代码扩展性。重点讲解了向上转型与向下转型的区别及其注意事项。
摘要由CSDN通过智能技术生成

多态,是面向对象三大特性之一。
在理解多态前先要明白向上转型和动态绑定

1.向上转型

是多态实现的前提之一:父类引用指向了子类实例。看起来像是把子类引用转成了父类引用,所有称做向上转型。。

第一种:直接赋值

public class Test {
    public static void main(String[] args) {
        Cat cat=new Cat();
        //Animal animal=null;
        //向上转型
        //animal=cat;
        //常见的写法
        Animal animal=new Cat();
    }
}

形式:FU fu=new Zi()
第二种:方法传参 本质上也是赋值

public class Test{
    public static void main(String [] args){
        fun(new Cat());
    }
    public static void fun(Animal animal){
        
    }
}

第三种:方法返回值

public class Test{
    public static void main(String [] args){
        Animal animal=fun();
    }
    public static Animal fun(){
        return new Cat();
    }
}

2.动态绑定

:是多态实现的第二个前提
如果父类的方法在子类中有同名同参数的方法(重写)时,就会发生动态绑定。 所谓动态/静态 是指“运行时”/”编译期“
Animal 类

public class Animal {
    public String name="圆圆";

    public void eat(){
        System.out.println("我是一只小动物");
        System.out.println(this.name+"正在吃饭");
    }
}

Cat类

public class Cat extends Animal{

    public void eat(){
        System.out.println("我是一只猫");
        System.out.println(this.name+"正在吃猫粮");
    }
}

Test类

public class Test{
    public static void main(String[] args) {
        Animal a1=new Cat();
        a1.eat();
    }
}

运行结果:
我是一只猫
圆圆正在吃猫粮

所谓动态绑定就是在执行父类子类共有的方法时,在运行时会看这个引用时指向父类还是子类 ,指向的是子类,就会执行子类的方法,指向的是父类,就会执行父类的方法。如果这个方法只在父类中存在,那么就不会发生动态绑定。如果这个方法只在子类种存在,编译器会直接报错。因为是父类引用,会去看父类有没有这个方法,没有会编译不通过。
多态所体现的语法细节就是向上转型,重写,动态绑定。
直观来看,多态就是一种引用,多种形态,下面通过一个例子来简单的感受一下多态。
Shape类

public class Shape {
    void draw(){

    }
}

Circle类

public class Circle extends Shape{
    void draw(){
        System.out.println("画一个⚪");
    }
}

Rect类

public class Rect extends Shape{
    void draw(){
        System.out.println("□");
    }
}

Triangle类

public class Triangle extends Shape{
    void draw(){
        System.out.println("🔺");
    }
}

Test类

public class Test{
    public static void main(String[] args) {
        Shape shape1=new Circle();
        Shape shape2=new Rect();
        Shape shape3=new Triangle();
        ShapeDraw(shape1);
        ShapeDraw(shape2);
        ShapeDraw(shape3);

    }
    public static void ShapeDraw(Shape shape){
        shape.draw();
    }
}

运行结果:
在这里插入图片描述

Test类种的main方法相当于类的调用者,多态的好处之一就是让类的调用者无需知道类的实现细节,以及类是什么类型都不用知道就可以来调用类,只要知道这个对象具有什么方法就好。例如 main方法中调用ShapeDraw方法,调用者只需要知道这是shape对象的方法,直接调用即可。
多态的第二个好处,减少使用大量的if -else 假如没有多态,那实现上面这个例子就需要用大量的if-else来判断对象是什么类型,具体执行哪个方法。
第三个好处:扩展性高,对于上面的例子,假如要新增一个形状,只需要再写一个类即可。对于类的调用者,也只需在ShapeDraw方法里new一个新的实例即可。改动成本减小许多

关于向下转型

父类对象转成子类对象

public class Animal {
    public String name="圆圆";

    public void eat(){
        System.out.println("我是一只小动物");
        System.out.println(this.name+"正在吃饭");
    }
}


public class Bird extends Animal{

    public void eat(){
        System.out.println("我是一只鸟");
        System.out.println(this.name+"正在吃谷子");
    }
    public void fly(){
        System.out.println(this.name+"正在飞");
    }
}


public class Test{
    public static void main(String[] args) {
        Animal animal=new Bird();
        animal.eat();
        //会报错
       animal.fly();
       
        
    }
}

在这里插入图片描述

父类中没有fly方法,直接调用会报错 虽然 animal 实际引用的是一个 Bird 对象, 但是编译器是以 animal 的类型来查看有哪些方法的.
要想让父类可以实现子类的fly方法,就需要向下转型

Bird bird=(Bird)animal;
bird.fly;

在这里插入图片描述

向下转型的不可靠的地方 如下语句:

Animal animal = new Cat("小猫");
Bird bird = (Bird)animal;
bird.fly();

animal本质上是一个Cat类型的对象,是不能转成Bird对象的,运行时会出异常.
为了解决这种情况,在使用向下转型时,先要判断这个引用是否是某个类的实例,使用instanceof ,如果是,返回true,继续进行向下转型。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值