您的位置:

多态的三种表现形式

多态是面向对象的重要概念之一,在Java等编程语言中得到了广泛的应用。多态主要指同一个方法或者类在不同的环境下呈现出不同的行为表现形式。根据Java中多态的表现形式不同,可以将其分为三类:方法重载、方法重写和接口实现。接下来从这三个方面,详细介绍多态的三种表现形式。

一、方法重载

方法重载,指的是在同一个类中定义多个同名的方法,但参数列表不同。这样,在调用方法时,根据实际传入的参数类型或个数的不同,会自动识别并调用相应的方法。方法的返回值和访问修饰符对方法重载并没有约束作用。

方法重载示例

public class Polygon {
    public void draw() {
        System.out.println("绘制图形");
    }
    public void draw(String color) {
        System.out.println("绘制" + color + "图形");
    }
    public void draw(int x, int y) {
        System.out.println("在(" + x + ", " + y + ")处绘制图形");
    }
}

在上述示例中,Polygon类中定义了三个同名方法draw(),但方法的参数列表分别为无参、一个String类型参数和两个int类型参数。以下是方法重载的使用示例:

Polygon polygon = new Polygon();
polygon.draw();            // 输出:绘制图形
polygon.draw("红色");      // 输出:绘制红色图形
polygon.draw(10, 20);      // 输出:在(10, 20)处绘制图形

通过上述示例,我们可以看出,由于Polygon.draw()方法被重载了,可以根据传入的参数类型或个数的不同,自动判断调用哪个方法。

二、方法重写

方法重写,指的是在子类中定义一个同名的方法,且方法签名(返回值类型、方法名、参数列表)与父类中的方法相同,从而实现对父类方法的重新编写。在方法重写中,子类中的方法将覆盖父类中同名的方法,这种覆盖是在运行时动态决定的。如果子类中的方法签名和父类中的方法签名不一致,那么子类中的方法在父类中就相当于是新增了一个方法,不是方法的重写。

方法重写示例

public class Animal {
    public void speak() {
        System.out.println("动物发出声音");
    }
}
public class Cat extends Animal {
    public void speak() {
        System.out.println("猫发出“喵喵喵”的声音");
    }
}
public class Dog extends Animal {
    public void speak() {
        System.out.println("狗发出“汪汪汪”的声音");
    }
}

在上述示例中,Animal类中定义了一个speak()方法,Cat类和Dog类分别继承Animal类,并分别重写了speak()方法。以下是方法重写的使用示例:

Animal animal1 = new Cat();
Animal animal2 = new Dog();
animal1.speak();    // 输出:猫发出“喵喵喵”的声音
animal2.speak();    // 输出:狗发出“汪汪汪”的声音

通过上述示例,我们可以看出,由于Cat类和Dog类重写了Animal类中的speak()方法,所以在调用时,会根据实际调用的对象类型,自动决定调用哪个方法。

三、接口实现

接口实现,指的是一个类实现了某个接口,并实现了该接口中定义的所有方法。在Java中,接口是一种抽象类型,其中只定义了方法签名和常量,而没有具体的方法实现。当一个类实现了某个接口,就必须实现接口中定义的所有方法。通过接口实现,可以实现不同类之间的代码复用,提高代码的可维护性和可重用性。

接口实现示例

public interface Shape {
    double area();      // 定义计算面积的方法
    double perimeter(); // 定义计算周长的方法
}
public class Circle implements Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }
    public double area() {
        return Math.PI * radius * radius;
    }
    public double perimeter() {
        return 2 * Math.PI * radius;
    }
}
public class Rectangle implements Shape {
    private double length;
    private double width;

    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }
    public double area() {
        return length * width;
    }
    public double perimeter() {
        return 2 * (length + width);
    }
}

在上述示例中,Shape接口定义了计算面积和周长的方法,Circle类和Rectangle类实现了Shape接口,并分别实现了area()和perimeter()方法。以下是接口实现的使用示例:

Shape shape1 = new Circle(5);
Shape shape2 = new Rectangle(3, 4);
System.out.println("圆的面积是:" + shape1.area());              // 输出:圆的面积是78.53981633974483
System.out.println("圆的周长是:" + shape1.perimeter());         // 输出:圆的周长是31.41592653589793
System.out.println("矩形的面积是:" + shape2.area());            // 输出:矩形的面积是12.0
System.out.println("矩形的周长是:" + shape2.perimeter());       // 输出:矩形的周长是14.0

通过上述示例,我们可以看出,由于Circle类和Rectangle类都实现了Shape接口,并实现了接口中定义的所有方法,所以在调用时,可以通过Shape类型的引用来调用其实现的方法。