通過應用實例討論Java多態的實現
實現Java多態
在代碼中實現Java的多態必須遵循的要求可歸納如下:
1.代碼中必須有超類和子類繼承關系。
2.超類提供作為接口的方法,對子類完善或者覆蓋這些方法指定規范。
3.參與多態的子類必須完善或者覆蓋這些指定的方法,以達到接口效應。
4.編寫驅動類,或者應用代碼,子類向上轉型為超類引用,實現多態。
下面小節應用實例分別討論如何實現多態。
超類提供Java多態接口
以計算圓形物體表面積和體積為例,討論多態對超類的要求以及如何提供多態接口:
- public abstract class Shape {
- ...
- // 以下定義抽象方法作為多態接口
- public abstract void computeArea();
- public abstract void computeVolume();
- public abstract double getArea(); //新增參與多態的接口方法
- public abstract double getVolume();
- }
除原來存在的兩個抽象方法外,因為getArea()和getVolume()也涉及和參與多態功能,因此將它們定義為實現多態的接口方法。另外多態的實現不影響任何其他運算和操作,所以這個代碼的其他部分無需修改。
當然執行多態的超類不必一定是抽象類。但因為在這個超類中,甚至大多數應用程序的超類中,只提供執行具體運算的方法的簽名,不可能提供具體代碼。所以應用抽象方法作為多態接口比較普遍。
如在計算公司雇員工資的超類中:
- // 用抽象方法作為多態接口
- public abstract class Employee {
- ...
- public abstract double earnings(); //定義抽象方法作為多態接口
- }
也可定義為普通方法,如:
- //這個方法將作為多態接口被子類的方法所覆蓋
- public class Manager extends Employee {
- ...
- public double eamings () return 0.0;
子類完善接口
在計算圓形物體表面積和體積的例子中,CircleShape2繼承了Shape,Circle繼承了CircleShape2。Circle類中完善了抽象超類指定的、作為多態接口的抽象方法如下:
- public class Circle extends CircleShape2 {
- ...
- double volume = 0.0; //Circle類沒有體積
- public void computeArea() { //完善超類作為多態接口的抽象方法
- area = Math.PI * radius * radius;
- }
- public double getArea() {
- return area;
- }
- public void computeVolume() {} //完善超類作為多態接口的抽象方法
- public double getVolume() {
- return volume;
- }
- }
代碼中完善了超類Shape規定的四個作為多態接口的抽象方法,實際上,已存在的Circle程序已經編寫了其中的兩個方法,只需要完善computeVolume()和getVolume()即可。Circle類沒有體積計算,所以ComputeVolume()為空程序體且getVolume()返回值為0.0。
以此類推,Sphere繼承了Circle,覆蓋了Circle的computeArea()和computeVolume():
- public class Sphere extends Circle{
- ...
- public void computeArea() { //覆蓋Circle的該方法
- super.computeArea(); //調用Circle的方法
- area = 4* area;
- }
- public void computeVolume() { //覆蓋Circle的該方法
- super.computeArea(); //調用Circle的方法
- volume = 4.0/3 * radius * area;
- }
- }
并且繼承了getArea()和getVolume()。顯而易見,抽象類和覆蓋技術的應用,已經為實現多態鋪平了道路。這里,只是對抽象類中指定的抽象方法,以及子類完善這些方法,從多態接口的角度加以新的內容和解釋。按照這個概念代碼技術,編寫計算員工工資的子類也是水到渠成的事。如:
- //Demo code
- public Manager extends Employee {
- ...
- public double earnings () {
- return baseSalary + meritPay + bonus;
- }
值得一提的是,如果超類中定義的作為多態接口的方法是一個完善了的普通方法,在子類中則需覆蓋它,以便實現多態。
如何使用Java的多態
調用多態方法是通過向上轉型,或稱超類引用實現的。即向上轉型后,由超類產生對子類多態方法的動態調用,如:
- Circle myCircle = new Circle(20.98);
- Shape shape = myCircle; //向上轉型或超類引用
- shape.computeArea();. //多態調用
- ...
應用鏈接表或集合,以及循環,則可有效地對大量的對象方法實行多態調用。本書將在以后的章節專門討論循環、鏈接表和集合技術。
如下是對計算圓形物體的表面積和體積實現多態調用的代碼:
- public class CircleShapeApp{
- public static void main(String[] args) {
- Circle circle = new Circle(12.98);
- Sphere sphere = new Sphere(25.55);
- Shape shape = circle; //向上轉型
- //多態調用
- shape.computeArea();
- shape.computeVolume();
- System.out.println("circle area: " + shape.getArea());
- System.out.println("circle volume: " + shape.getVolume());
- //多態調用
- shape = sphere;
- shape.computeArea();
- shape.computeVolume();
- System.out.println("Sphere area: " + shape.getArea());
- System.out.println("Sphere volume: " + shape.getVolume());
- }
- }
這里對Circle對象多態調用computeVolume()毫無意義,僅是為了演示目的。其運行結果為:
- circle area: 529.2967869138698
- circle volume: 0.0
- Sphere area: 2050.8395382450512
- Sphere volume: 69865.26693621474
如果需要多態調用大量對象,可以使用數組和循環如下:
- ...
- for(int i = 0; i < objNum; i++) { //循環objNum次
- shape[i].computeArea(); //i從0到objNum-1
- shape[i].computeVolume();
- System.out.println("The area: " + shape[i].getArea());
- System.out.println("The volume: " + shape[i].getVolume());
- }
這個循環語句也被稱為多態管理循環。
Java的多態就先介紹到這里。本文出自 “海外咖啡豆 - 高永強的博客天地” 博客。
【編輯推薦】