1.多态的基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
2.多态的具体体现
1)方法的多态
public class PloyMethod { public static void main(String[] args) {
//方法重载体现多态
A a = new A();
//这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态
System.out.println(a.sum(10, 20));
System.out.println(a.sum(10, 20, 30));
//方法重写体现多态
B b = new B();
a.say();
b.say();
}
}
class B {
//父类
public void say() {
System.out.println("B say() 方法被调用...");
}
}
class A extends B {
//子类
public int sum(int n1, int n2){
//和下面 sum 构成重载
return n1 + n2;
}
public int sum(int n1, int n2, int n3){
return n1 + n2 + n3;
}
public void say() {
System.out.println("A say() 方法被调用..."); } }
2)对象的多态`
public class Animal {
public void cry() {
System.out.println("Animal cry() 动物在叫....");
}
}
public class Cat extends Animal {
public void cry() {
System.out.println("Cat cry() 小猫喵喵叫...");
}
public class Dog extends Animal {
public void cry() {
System.out.println("Dog cry() 小狗汪汪叫...");
}
}
public class PolyObject {
public static void main(String[] args) {
//体验对象多态特点
//animal 编译类型就是 Animal , 运行类型 Dog
Animal animal = new Dog();
//因为运行时 , 执行到改行时,animal 运行类型是 Dog,所以 cry 就是 Dog 的 cry
animal.cry(); //小狗汪汪叫
//animal 编译类型 Animal,运行类型就是 Cat
animal = new Cat();
animal.cry(); //小猫喵喵叫
}
}
3.多态入门案例
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 对应的实例相关), 这种行为就称为 多态。
4.多态的使用细节
1)多态的前提是:两个对象(类)存在继承关系。
2)多态的向上转型: 本质:父类的引用指向了子类的对象;
语法:父类类型引用名=new 子类类型();
特点:编译类型看左边,运行类型看右边。
可以调用父类中的所有成员(需遵守访问权限),不能调 用子类中特有成员;
3)多态的向下转型:语法:子类类型引用名=(子类类型)父类引用;
只能强转父类的引用,不能强转父类的对象;
要求父类的引用必须指向的是当前目标类型的对象;
当向下转型后,可以调用子类类型中所有的成员。
5.使用多态的好处
- 类调用者对类的使用成本进一步降低。
封装是让类的调用者不需要知道类的实现细节。
多态能让类的调用者连这个类的类型是什么都不必知道, 只需要知道这个对象具有某个方法即可。 - 能够降低代码的 “圈复杂度”, 避免使用大量的 if - else。
- 可扩展能力更强。
6.总结
多态是面向对象程序设计中比较难理解的部分.。我们会在后面的抽象类和接口中进一步体会多态的使用.。重点是多态带来的编码上的好处。
另一方面, 如果抛开 Java, 多态其实是一个更广泛的概念, 和 “继承” 这样的语法并没有必然的联系。
C++ 中的 “动态多态” 和 Java 的多态类似,但是 C++ 还有一种 “静态多态”(模板), 就和继承体系没有关系了。
Python 中的多态体现的是 “鸭子类型”, 也和继承体系没有关系。
Go 语言中没有 “继承” 这样的概念, 同样也能表示多态。
无论是哪种编程语言, 多态的核心都是让调用者不必关注对象的具体类型. 这是降低用户使用成本的一种重要方式。