Java 多态

欢马劈雪     最近更新时间:2020-08-04 05:37:59

173

多态性是指对象能够有多种形态。在 OOP 中最常用的多态性发生在当父类引用指向孩子类对象时。

任何能够通过一个以上的 IS-A 测试的 Java 对象被认为是多态的。在 Java 中所有对象都是多态的,因为任何一个对象都会有一个他们自己类型的和 Object 类的 IS-A 关系。

重要的是知道,通过引用变量是唯一可以用来访问一个对象的方法。引用变量可以只有一个类型。引用变量一旦被声明是不能被改变的。

引用变量能够重新分配到其他提供的没有被声明为 final 的对象。引用变量的类型将决定它可以调用的对象的方法。

一个引用变量能够引用任何一个对象的声明类型或任何声明类型的子类型。一个引用变量可以声明为一个类或接口类型。

示例

让我们看下面的例子:

public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}

现在 Deer 类是多态的,因为他有多个继承机制。针对上面的例子有以下说法:

  • Deer 就是 Animal
  • Deer 就是 Vegetarian
  • Deer 就是 Deer
  • Deer 就是 Object

当我们提供引用变量来引用 Deer 对象,下面的声明是合法的:

Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;

所有的引用变量 d, a, v, o 在堆中引用同一个对象 Deer。

虚方法

在这一节中,将展示在 Java 中被覆盖方法的行为在设计类时是如何体现多态性的好处的。

我们已经讨论了覆盖方法,一个子类可以覆盖它父类的方法。一个被覆盖的方法实际上隐藏在父类当中,并且不会被调用,除非子类在覆盖方法中用 super 关键字。

/* File name : Employee.java */
public class Employee
{
   private String name;
   private String address;
   private int number;
   public Employee(String name, String address, int number)
   {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + this.name
       + " " + this.address);
   }
   public String toString()
   {
      return name + " " + address + " " + number;
   }
   public String getName()
   {
      return name;
   }
   public String getAddress()
   {
      return address;
   }
   public void setAddress(String newAddress)
   {
      address = newAddress;
   }
   public int getNumber()
   {
     return number;
   }
}

现在我们如下继承 Employee 类:

/* File name : Salary.java */
public class Salary extends Employee
{
   private double salary; //Annual salary
   public Salary(String name, String address, int number, double
      salary)
   {
       super(name, address, number);
       setSalary(salary);
   }
   public void mailCheck()
   {
       System.out.println("Within mailCheck of Salary class ");
       System.out.println("Mailing check to " + getName()
       + " with salary " + salary);
   }
   public double getSalary()
   {
       return salary;
   }
   public void setSalary(double newSalary)
   {
       if(newSalary >= 0.0)
       {
          salary = newSalary;
       }
   }
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
}

现在,你仔细研究下面的程序,试图确定它的输出:

/* File name : VirtualDemo.java */
public class VirtualDemo
{
   public static void main(String [] args)
   {
      Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
      Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
      System.out.println("Call mailCheck using Salary reference --");
      s.mailCheck();
      System.out.println("\n Call mailCheck using Employee reference--");
      e.mailCheck();
    }
}

这将产生如下的结果:

展开阅读全文