理解多态
多态的的概念:
代码示例: 打印多种形状
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("♣");
}
}
/我是分割线//
// Test.java
public class Test {
public static void main(String[] args) {
Shape shape1 = new Flower();
Shape shape2 = new Cycle();
Shape shape3 = new Rect();
drawMap(shape1);
drawMap(shape2);
drawMap(shape3);
}
// 打印单个图形
public static void drawShape(Shape shape) {
shape.draw();
}
}
在这个代码中, 分割线上方的代码是 类的实现者 编写的, 分割线下方的代码是 类的调用者 编写的.
当类的调用者在编写 drawMap 这个方法的时候, 参数类型为 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();
}
}
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("△");
}
}
对于类的调用者来说(drawShapes方法), 只要创建一个新类的实例就可以了, 改动成本很低.
而对于不用多态的情况, 就要把 drawShapes 中的 if - else 进行一定的修改, 改动成本更高。
抽象类:包含抽象方法的类 抽象类
- 1、抽象类不能进行实例化 ; * 2、在抽象类当中,可以拥有和普通类一样的数据成员和方法 * public int age;
- public static int count; * public void func() {}
- 3、抽象类是可以被继承的,可以发生向上转型。 *
4、当一个普通类继承了一个抽象类,那么注意,当前这个普通类,一定要重写抽象类当中的抽象方法。 *- 5、当普通类A继承了抽象类,且不想实现抽象类当中的抽象方法的时候
那么这个普通类可以被修改为抽象类A,此时就不需要进行实现了,当然你也可以实现。 *
如果一个普通类B,继承了这个抽象类A,此时就要实现这个抽象方法。- 6、抽象方法不能是private修饰的,因为抽象方法就是用来被重写的
- 7、抽象类的出现 其实最大的意义就是为了被继承。
接口:使用关键字 interface修饰
- 1、接口当中的方法 ,不能有具体实现。 * 接口当中的方法,默认是:public abstract
- 2、接口当中的成员变量,默认是 public static final
- 3、JDK1.8引入的新特性。default修饰的方法,默认方法,可以有具体的实现
4、接口不可以进行实例化;- 5、类和接口之间的关系是,implements
- 6、一个类可以实现多个接口class Test implements A,B,C{
- 7、一个类可以继承类,同时实现多个接口 * class Test extends TestAbstract implements A,B,C{
- 8、接口可以扩展多个接口:interface D extends A,B,C { * 所以 接口的出现就是为了解决java多继承的问题