Java 多态性

在本教程中,我们将借助示例了解 Java 多态性及其实现。

在本教程中,我们将借助示例了解 Java 多态性及其实现。

多态是面向对象编程的一个重要概念。它只是意味着事物不止一种形式。

也就是说,同一个实体(方法或操作符或对象)可以在不同的场景中执行不同的操作。

示例:Java 多态性

// 多边形
public class Polygon {

  // 绘制多边形
  public void render() {
    System.out.println("Rendering Polygon...");
  }
}

// 正方形
public class Square extends Polygon {

  // 绘制正方形
  public void render() {
    System.out.println("Rendering Square...");
  }
}

// 圆形
public class Circle extends Polygon {

  // 绘制圆形
  public void render() {
    System.out.println("Rendering Circle...");
  }
}

public class Main {
  public static void main(String[] args) {

    // 正方形对象
    Square s1 = new Square();
    s1.render();

    // 圆形对象
    Circle c1 = new Circle();
    c1.render();
  }
}

输出

Rendering Square...
Rendering Circle...

在上面的例子中,我们创建了一个父类 Polygon(多边形) 和两个子类 Square (正方形) 与 Circle (圆形)。

注意 render() 方法的使用。 render() 方法的主要目的是绘制形状。但是,绘制正方形的过程与绘制圆形的过程不同。

也就是时说,render() 方法在不同的类中表现不同。因此,我们可以说 render() 是多态的。

为什么是多态?

多态允许我们创建一致的代码。在前面的例子中,我们可以分别创建不同的方法 renderSquare()renderCircle() 来绘制正方形和圆圈。

这也能正常工作。但是,对于每种形状,我们都需要创建不同的方法,这会让代码变得复杂和不易维护。

为了解决这个问题,Java 中的多态性允许我们创建一个 render() 的方法,该方法对于不同的形状会有不同的表现。

注意:该 print() 方法也是多态的一个例子。它被用于打印不同类型的喜欢的值 charintstring 等。

我们可以使用以下方式在 Java 中实现多态:

  1. 方法覆盖
  2. 方法重载
  3. 运算符重载

Java 方法覆盖

Java 继承章节了解到,如果父类和子类中都存在相同的方法。子类中的方法会覆盖从父类继承的方法。这称为方法覆盖。

在这种情况下,同一个方法将在父类中执行一个操作,在子类中执行另一个操作。例如,

示例 1:使用方法覆盖的多态性

public class Language {
  public void displayInfo() {
    System.out.println("Common English Language");
  }
}

public class Java extends Language {
  @Override
  public void displayInfo() {
    System.out.println("Java Programming Language");
  }
}

public class Main {
  public static void main(String[] args) {

    Java j1 = new Java();
    j1.displayInfo();

    Language l1 = new Language();
    l1.displayInfo();
  }
}

输出

Java Programming Language
Common English Language

在上面的例子中,我们创建了一个 Language 类作为父类和一个 Java 类作为子类。并且 Java 类覆盖了父类的 displayInfo() 方法。

Language 类和 Java 类的对象分别调用 displayInfo() 方法打印信息的时候,他们输出了不同的信息。

根据调用方法的对象的具体类型,打印相应的信息。

注意:调用的方法是在程序执行过程中确定的。因此,方法覆盖是一种运行时多态性

Java 方法重载

在 Java 类中,如果参数不同,我们可以创建具有相同名称的方法。例如,

void func() { ... }
void func(int a) { ... }
float func(double a) { ... }
float func(int a, float b) { ... }

这称为方法重载。这里,同样的方法会根据参数的不同执行不同的操作。

示例 3:使用方法重载的多态性

public class Pattern {

  // 重载方法:无参数
  public void display() {
    for (int i = 0; i < 10; i++) {
      System.out.print("*");
    }
  }

  // 重载方法:1 个参数
  public void display(char symbol) {
    for (int i = 0; i < 10; i++) {
      System.out.print(symbol);
    }
  }
}

public class Main {
  public static void main(String[] args) {
    Pattern d1 = new Pattern();

    // call method without any argument
    d1.display();
    System.out.println("\n");

    // call method with a single argument
    d1.display('#');
  }
}

输出

**********
##########

在上面的例子中,我们创建了一个 Pattern 类,该类包含重载的 display() 方法。

display() {...}

display(char symbol) {...}

在这里, display() 的主要功能是打印图案。但是,根据传递的参数,该方法打印不同的图案:

  • 如果没有传递参数或,打印的是 10 个 *
  • 如果传递 char 类型字符参数,则打印 10 个给定的字符。

注意:调用的方法由编译器决定。因此,它也被称为编译时多态。

Java 运算符重载

Java 中的一些运算符对不同的操作数有不同的表现。例如,

  • + 运算符被重载以执行数字加法和字符串连接
  • & , |! 之类的运算符 被重载用于逻辑运算和按位运算。

让我们看看如何使用运算符重载来实现多态性。

+ 运算符的操作数有两个,但是根据操作数的类型不同具有不同的表现:

  • + 的两个操作数都是数字的时候,执行数学加法操作。例如,

    int a = 5;
    int b = 6;
    
    int sum = a + b;  // 11
    
  • + 的两个操作数有一个是字符串的时候,执行字符串连接操作。例如,

    String first = "Java ";
    String second = "Programming";
    
    name = first + second;  // ava Programming
    

在这里,我们可以看到 + 运算符在 Java 中被重载以执行两个操作:加法字符串连接

! 注意:在像 C++ 这样的语言中,我们可以自定义运算符以针对不同的操作数进行不同的工作。但是,Java 不支持用户定义的运算符重载。

多态变量

如果变量在不同条件下指代不同的值,则称为多态变量。

对象变量(实例变量)表示 Java 中多态变量的行为。这是因为一个类的对象变量可以引用它的类的对象,也可以引用它的子类的对象。

示例:多态变量

public class ProgrammingLanguage {
  public void display() {
    System.out.println("I am Programming Language.");
  }
}

public class Java extends ProgrammingLanguage {
  @Override
  public void display() {
    System.out.println("I am Object-Oriented Programming Language.");
  }
}

public class Main {
  public static void main(String[] args) {

    // 声明一个对象变量
    ProgrammingLanguage pl;

    // 赋值为当前类的实例
    pl = new ProgrammingLanguage();
    pl.display();

    // 赋值为子类的实例
    pl = new Java();
    pl.display();
  }
}

输出

I am Programming Language.
I am Object-Oriented Programming Language.

在上面的例子中,我们有一个 ProgrammingLanguage 类作为父类,并创建了一个父类的对象 plpl 多态的,因为:

  • 在声明中 pl = new ProgrammingLanguage()plProgrammingLanguage 的实例。
  • 在声明中 pl = new Java()plJava 的实例。

这是 Java 中向上转换的示例。这也是一个典型的运行时多态。