详解Java面向对象之多态的原理与实现
什么是多态?
多态是面向对象编程中的一种重要特性,它允许我们使用一个对象的不同形态来完成不同的操作。简单来说,多态就是指不同对象对同一消息作出不同的响应。
比如说有一个接口(或者抽象类)Animal
,有两个具体的子类Cat
和Dog
,它们都有一个方法makeSound()
,但是它们的具体实现是不同的。
interface Animal {
void makeSound();
}
class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("喵喵喵~");
}
}
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("汪汪汪~");
}
}
现在我们可以创建一个数组,其中存放了 3 个Animal
对象,其中包括 2 个Cat
对象和 1 个Dog
对象,然后我们可以依次调用它们的makeSound()
方法,它们会根据自己的具体实现发出不同的声音。
public static void main(String[] args) {
Animal[] animals = new Animal[]{new Cat(), new Dog(), new Cat()};
for (Animal animal : animals) {
animal.makeSound();
}
}
输出结果为:
喵喵喵~
汪汪汪~
喵喵喵~
多态的原理
Java 语言实现多态的关键是通过向上转型(Upcasting)和向下转型(Downcasting)实现的。
向上转型
向上转型指的是将子类对象转型成父类对象的过程,这是一个自动的过程,不需要显式地进行强制类型转换。
Cat cat = new Cat();
Animal animal = cat; // 向上转型
在上面的代码中,Cat
对象赋值给了Animal
类型的变量,实际上发生了向上转型的过程。这就意味着我们可以把Cat
对象当作Animal
对象来使用,但是我们只能调用Animal
中定义的方法,而不能调用Cat
独有的方法。
向下转型
向下转型指的是将父类对象转型成子类对象的过程,这是一个显式的过程,需要使用强制类型转换。
Animal animal = new Cat();
Cat cat = (Cat) animal; // 向下转型
在上面的代码中,Animal
对象赋值给了Cat
类型的变量,但是由于Cat
是Animal
的子类,所以需要进行强制类型转换。这意味着我们可以调用Cat
独有的方法了。
需要注意的是,向下转型存在风险,如果转换的对象不是目标类型的实例,则会抛出ClassCastException
异常。为了避免出现这种情况,我们可以使用instanceof
关键字来进行类型判断。
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.catchMouse(); // 如果是Cat的实例,可以调用catchMouse方法
}
示例1:实现一个简单的图形绘制程序
下面我们通过一个示例来说明多态的应用。
假设有一个图形绘制程序,包括三种不同的图形:圆形(Circle
)、矩形(Rectangle
)和三角形(Triangle
)。它们都有一个draw()
方法来绘制图形。我们可以定义一个抽象的Shape
类来表示这些图形,然后分别定义具体的子类来实现draw()
方法。
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
@Override
void draw() {
System.out.println("绘制圆形");
}
}
class Rectangle extends Shape {
@Override
void draw() {
System.out.println("绘制矩形");
}
}
class Triangle extends Shape {
@Override
void draw() {
System.out.println("绘制三角形");
}
}
现在我们可以写一个绘制图形的函数,它接收一个Shape
类型的参数,然后调用它的draw()
方法进行绘制。
public static void drawShape(Shape shape) {
shape.draw();
}
然后我们可以创建不同的图形对象来绘制图形。
public static void main(String[] args) {
drawShape(new Circle());
drawShape(new Rectangle());
drawShape(new Triangle());
}
这里的关键是将Circle
、Rectangle
和Triangle
对象都赋值给了Shape
类型的变量,实际上发生了向上转型的过程。然后我们将它们传给了drawShape()
函数,由于这个函数接收的参数是Shape
类型,所以它们会被当作Shape
对象来使用,但是在调用它们的draw()
方法的时候,实际上调用的是具体子类的实现。
运行结果如下:
绘制圆形
绘制矩形
绘制三角形
这就是多态的一个典型应用。
示例2:实现一个简单的计算器程序
另一种经典的多态应用场景是实现不同类型的计算器。
假设有一个计算器程序,它可以支持两种不同的计算方式:加法(AddOperation
)和乘法(MultiplyOperation
),我们可以定义一个接口Operation
来表示这些计算方式,然后分别定义具体的类来实现Operation
接口。
interface Operation {
int calculate(int a, int b);
}
class AddOperation implements Operation {
@Override
public int calculate(int a, int b) {
return a + b;
}
}
class MultiplyOperation implements Operation {
@Override
public int calculate(int a, int b) {
return a * b;
}
}
现在我们可以写一个计算器程序,它接收两个整数和一个Operation
对象,然后调用它的calculate()
方法进行计算。
public static int calculate(int a, int b, Operation operation) {
return operation.calculate(a, b);
}
然后我们可以创建不同的Operation
对象来进行计算。
public static void main(String[] args) {
System.out.println(calculate(1, 2, new AddOperation()));
System.out.println(calculate(3, 4, new MultiplyOperation()));
}
这里的关键是将AddOperation
和MultiplyOperation
对象都赋值给了Operation
类型的变量,实际上发生了向上转型的过程。然后我们将它们传给了calculate()
函数,由于这个函数接收的参数是Operation
类型,所以它们会被当作Operation
对象来使用,但是在调用它们的calculate()
方法的时候,实际上调用的是具体子类的实现。
运行结果如下:
3
12
这就是多态的另一个典型应用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Java面向对象之多态的原理与实现 - Python技术站