什么是多态 -- 《JAVA编程思想》21

封装、继承、多态 是 JAVA 语言的三大基本特征,今天我们就来聊聊其中的多态。

多态通过分离做什么怎么做,将接口和实现分离开来,不但能够改善代码的组合结构和可读性,还能不断扩展现有程序,是一项让程序员将“改变的事物和未改变的事物分离开”的重要技术。

先来看一个经典案例,创建一个 Shape 基础、类表示几何形状,再分别创建三个导出类 Circle 表示圆,Square 表示矩形,Trangle 表示三角形,最后编写工具类 Sceen 绘制/擦写几何图形:

public class Shape {

    public void draw() {
        System.out.println("shape draw");
    }

    public void erase() {
        System.out.println("shape erase");
    }
}
public class Circle extends Shape {

    public void erase() {
        System.out.println("circle erase");
    }

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

    public void erase() {
        System.out.println("square erase");
    }

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

    public void erase() {
        System.out.println("triangle erase");
    }

    public void draw() {
        System.out.println("triangle draw");
    }
    
}
public class Screen {

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

    public static void shapeErase(Shape shape) {
        shape.erase();
    }

    public static void main(String[] args) {
        Shape shape = new Shape();
        shapeDraw(shape);
        Circle circle = new Circle();
        shapeDraw(circle);
        Square square = new Square();
        shapeDraw(square);
        Triangle triangle = new Triangle();
        shapeDraw(triangle);
    }

}
shape draw
circle draw
square draw
triangle draw

我们可以看到 Sceen 类中的 shapeDraw() 方法不仅能接受指定的 Shape 类型参数,还可以接受来自 Shape 类的各种导出类。

当一个 Shape 的导出类传递到 shapeDraw() 方法时,编译器会触发向上转型,将 Circle、Square、Trangle 等导出类转换为基类 Shape ,但调用的方法还是导出类自身的方法,这便是我们今天要学习的多态。

这里也行有人会有疑问,为什么不明确指定 shapeDraw() 需要的对象类型呢?为每一个 shape 导出类编写方法,代码不是更为直观嘛?

倘若按上述所说,之后再加入其他的几何形状:sector (菱形)、trapezoid(梯形),都需要额外再编写一个新的 shapeDraw() 方法。这样做会带来几个缺点:

1.为每一个类编写方法,会增加编程工作量

2.因为它们都来自相同的基类,方法的行为也基本类似,为每一个几何类型编写类似的方法,势必会增加很多重复代码,增加代码维护成本

3.为保证每个几何类型都是调用 shapeDraw() 方法,肯定会进行方法重载,倘若忘记为某一个几何类型进行重载,编译器也不会报错,但最终会影响程序的运行

不过利用多态的机制,便可以轻松地解决上述问题。当我们需要为系统添加更多的新类型时,不需要更改 shapeDraw() 方法,只需要新类型遵循 shape 类的模型,与基类接口通信即可,大幅提升了程序的可扩展性。

不过这里还有一个问题:编译器是怎么知道传入的 shape 参数具体是哪个导出类呢?

这里不得不提,JAVA 方法的调用绑定机制。若在程序执行前将方法参数与编译器进行绑定,则称为前期绑定,在程序运行期必须明确参数类型。显然 JAVA 多态使用的不是这种机制,这里使用的是与之相反的“后期绑定”,也被称作为动态绑定或者运行时绑定,在程序运行时根据对象的类型进行绑定。

JAVA 中除了 static 方法和 final 方法(private 方法属于 final 方法)之外,其他所有的方法都是后期绑定。

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BaymaxCS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值