Java教程 专题
专题目录
您的位置:java > Java教程专题 > Java 多态
Java 多态
作者:--    发布时间:2019-11-20

多态是同一个行为具有多个不同表现形式或形态的能力。

多态性是对象多种表现形式的体现。

比如我们说"宠物"这个对象,它就有很多不同的表达或实现,比如有小猫、小狗、蜥蜴等等。那么我到宠物店说"请给我一只宠物",服务员给我小猫、小狗或者蜥蜴都可以,我们就说"宠物"这个对象就具备多态性。

接下来让我们通过实例来了解java的多态。

例子

public interface vegetarian{}
public class animal{}
public class deer extends animal implements vegetarian{}

因为deer类具有多重继承,所以它具有多态性。以上实例解析如下:

  • 一个 deer is-a(是一个) animal
  • 一个 deer is-a(是一个) vegetarian
  • 一个 deer is-a(是一个) deer
  • 一个 deer is-a(是一个)object

在java中,所有的对象都具有多态性,因为任何对象都能通过is-a测试的类型和object类。

访问一个对象的唯一方法就是通过引用型变量。

引用型变量只能有一种类型,一旦被声明,引用型变量的类型就不能被改变了。

引用型变量不仅能够被重置为其他对象,前提是这些对象没有被声明为final。还可以引用和它类型相同的或者相兼容的对象。它可以声明为类类型或者接口类型。

当我们将引用型变量应用于deer对象的引用时,下面的声明是合法的:

deer d = new deer();
animal a = d;
vegetarian v = d;
object o = d;

所有的引用型变量d,a,v,o都指向堆中相同的deer对象。


虚方法

我们将介绍在java中,当设计类时,被重写的方法的行为怎样影响多态性。

我们已经讨论了方法的重写,也就是子类能够重写父类的方法。

当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。

要想调用父类中被重写的方法,则必须使用关键字super。

/* 文件名 : 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类:

/* 文件名 : 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;
   }
}

现在我们仔细阅读下面的代码,尝试给出它的输出结果:

/* 文件名 : 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();
    }
}

以上实例编译运行结果如下:

constructing an employee
constructing an employee
call mailcheck using salary reference --
within mailcheck of salary class
mailing check to mohd mohtashim with salary 3600.0

call mailcheck using employee reference--
within mailcheck of salary class
mailing check to john adams with salary 2400.0

例子中,我们实例化了两个salary对象。一个使用salary引用s,另一个使用employee引用。

编译时,编译器检查到mailcheck()方法在salary类中的声明。

在调用s.mailcheck()时,java虚拟机(jvm)调用salary类的mailcheck()方法。

因为e是employee的引用,所以调用e的mailcheck()方法则有完全不同的结果。

当编译器检查e.mailcheck()方法时,编译器检查到employee类中的mailcheck()方法。

在编译的时候,编译器使用employee类中的mailcheck()方法验证该语句, 但是在运行的时候,java虚拟机(jvm)调用的是salary类中的mailcheck()方法。

该行为被称为虚拟方法调用,该方法被称为虚拟方法。

java中所有的方法都能以这种方式表现,借此,重写的方法能在运行时调用,不管编译的时候源代码中引用变量是什么数据类型。

网站声明:
本站部分内容来自网络,如您发现本站内容
侵害到您的利益,请联系本站管理员处理。
联系站长
373515719@qq.com
关于本站:
编程参考手册