1. 程式人生 > >尼古拉.特斯拉----部落格專欄

尼古拉.特斯拉----部落格專欄

宣告為父類型別的引用變數只能呼叫父類中的方法,如果此變數實際引用的是子類物件,而子類物件中覆蓋了父類的方法,這時父類物件呼叫的是子類中的方法,這種機制就成為虛方法呼叫。所以,同樣的兩個引用變數呼叫相同的方法結果可能不同。
父類與子類之間的多型性,對父類的函式進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和引數,我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時子類並不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要採用方法的重寫。方法重寫又稱方法覆蓋。
若子類中的方法與父類中的某一方法具有相同的方法名、返回型別和引數表,則新方法將覆蓋原有的方法。如需父類中原有的方法,可使用super關鍵字,該關鍵字引用了當前類的父類。
子類函式的訪問修飾許可權不能少於父類的;


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;
}
}










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;
}
}








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();
}
}


我們例項化了兩個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中所有的方法都能以這種方式表現,藉此,重寫的方法能在執行時呼叫,不管編譯的時候原始碼中引用變數是什麼資料型別。