理解多态
有了面的向上转型, 动态绑定, 方法重写之后, 我们就可以使用 多态(polypeptide) 的形式来设计程序了.我们可以写一些只关注父类的代码, 就能够同时兼容各种子类的情况.
代码示例:
package com.bit.scr1;
/**
* @ Created with IntelliJ IDEA.
* @ClassName TestDemo2
* @Description
* @Author by
* @Date 2020/4/4 18:32
*/
class Shape {
public void Draw() {
}
}
class Cycle extends Shape {
@Override
public void Draw() {
System.out.println("这是一个○!");
}
}
class Rect extends Shape{
@Override
public void Draw() {
System.out.println("这是一个矩形!");
}
}
class Flower extends Shape {
@Override
public void Draw() {
System.out.println("花一朵蕐");
}
}
public class TestDemo2 {
public static void drawFun(Shape shape) {
shape.Draw();
}
public static void main(String[] args) {
Shape[] shapes = {new Cycle(),new Rect(),new Flower()};
for (Shape shape:shapes) {
shape.Draw();
System.out.println("=========");
drawFun(shape);
System.out.println("================");
}
}
public static void main1(String[] args) {
Shape shape1 = new Rect();
shape1.Draw();
Shape shape2 = new Cycle();
shape2.Draw();
System.out.println("=================");
drawFun(shape1);
drawFun(shape2);
}
}
当类的调用者在编写 drawFun 这个方法的时候, 参数类型为 Shape (父类), 此时在该方法内部并不知道, 也不关注当前的 shape 引用指向的是哪个类型(哪个子类)的实例. 此时 shape 这个引用调用 draw 方法可能会有多种不同的表现(和 shape 对应的实例相关), 这种行为就称为 多态.
1、多态顾名思义, 就是 “一个引用, 能表现出多种不同形态”
举个具体的例子. 汤老湿家里养了两只鹦鹉(圆圆和扁扁)和一个小孩(核弹). 我媳妇管他们都叫 “儿子”. 这时候我对我媳妇说, “你去喂喂你儿子去”. 那么如果这里的 “儿子” 指的是鹦鹉, 我媳妇就要喂鸟粮; 如果这里的 “儿子” 指的是核弹, 我媳妇就要喂馒头.
2、那么如何确定这里的 “儿子” 具体指的是啥? 那就是根据我和媳妇对话之间的 “上下文”.代码中的多态也是如此. 一个引用到底是指向父类对象, 还是某个子类对象(可能有多个), 也是要根据上下文的代码来确定.
使用多态的好处是什么?
- 类调用者对类的使用成本进一步降低.
封装是让类的调用者不需要知道类的实现细节.
多态能让类的调用者连这个类的类型是什么都不必知道, 只需要知道这个对象具有某个方法即可,因此, 多态可以理解成是封装的更进一步, 让类调用者对类的使用成本进一步降低. - 能够降低代码的 “圈复杂度”, 避免使用大量的 if - else
public static void drawShapes() {
Rect rect = new Rect();
Cycle cycle = new Cycle();
Flower flower = new Flower();
String[] shapes = {"cycle", "rect", "cycle", "rect", "flower"};
for (String shape : shapes) {
if (shape.equals("cycle")) {
cycle.draw();
} else if (shape.equals("rect")) {
rect.draw();
} else if (shape.equals("flower")) {
flower.draw();
}
}
}
如果使用使用多态, 则不必写这么多的 if - else 分支语句, 代码更简单.
public static void drawShapes() {
// 我们创建了一个 Shape 对象的数组.
Shape[] shapes = {new Cycle(), new Rect(), new Cycle(),
new Rect(), new Flower()};
for (Shape shape : shapes) {
shape.draw();
}
}
- 可扩展能力更强.
如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低