顯示具有 多型 標籤的文章。 顯示所有文章
顯示具有 多型 標籤的文章。 顯示所有文章

2021年7月13日 星期二

JAVA 物件導向的概念-14 多型的練習

   上一篇練習的多型,其承接物件時是使用父類別所宣告的物件,這次嚐試用介面所宣告的物件來承接。

  英雄與惡棍都會被世界所記錄,死後也都有葬禮,但方式都不同,所以我抽出記錄與葬禮各自寫成介面。

記錄介面:

// 記錄的介面
public interface Record {
void recordWay();
}

葬禮的介面:

// 葬禮的介面
public interface Burial {
void burialWay();
}

然後再寫出英雄與惡棍的類別,並實作上述兩個介面,而且內容要覆寫介面的方法。

英雄類別:

// 英雄類別
public class Hero implements Burial, Record {

public void burialWay(){
System.out.println("使用國葬!");
}

public void recordWay(){
System.out.println("製造雕像紀念!");
}
}

惡棍類別:

// 惡棍類別
public class Gangster implements Burial, Record {

public void burialWay(){
System.out.println("丟去餵野狗!");
}

public void recordWay(){
System.out.println("寫入罪犯啟示錄中!");
}
}

在主程式中的工作與前一篇相同,

主程式:

// 主程式
public class Main {
    public static void burialDeal(Burial man) {
man.burialWay();
}

public static void recordDeal(Record man) {
man.recordWay();
}
public static void main(String[] args){

Hero ai = new Hero(); // 宣告愛未未是一個英雄物件,並產生她。
Gangster atnans = new Gangster(); // 宣告亞特南斯是一個惡棍物件,並產生他。

System.out.println("英雄愛未未的下場~~");
burialDeal(ai);
recordDeal(ai);

System.out.println();

System.out.println("惡棍亞特南斯的下場~~");
burialDeal(atnans);
recordDeal(atnans);

}

}

結果:

英雄愛未未的下場~~
製造雕像紀念!
使用國葬!

惡棍亞特南斯的下場~~
寫入罪犯啟示錄中!
丟去餵野狗!

Process finished with exit code 0

下個結論~~多型基本上就是模糊化寫法的進階應用!

  上一篇是用方法中宣告的[父類別物件]去承接[子類別物件],這一篇則是用方法中宣告的[介面]去承接[實作該介面的類別產生之物件]。

  物件導向的概念大概就是這樣,實際上我手邊的書還有教巢狀類別、聚合之類的,不過我朋友 Elton 認為那些以後需要再學就好,所以我就果斷跳過了。接下來我要學的就是套件。

  最後說一下,如果你已經到學到這邊,那接下來就請不要放棄,因為接下來就是學用別人的套件,你不需要知道內容原理,只要知道如何用就好了。而這些資源,網路上很多,善用這些資源,你就像是有超能力一樣,可以完成很多事情。簡單說,回報現在才開始。



JAVA 物件導向的概念-13 複習模糊化寫法、過載特性,多型

   在看多型章節時發現多型和模糊化寫法、過載有相似之處,故決定開頭先複習,再介紹多型。

  先複習模糊化寫法,在兩個類別是繼承關係時,我們可以使用模糊化寫法宣告物件,例如父類別是人類 Human,其中一個子類別是騎士 Kinght,我們宣告藍斯洛特是騎士時,可以寫作

Kinght lancelot = new Kinght();// 明確宣告藍斯洛特為一個騎士,口語說法:騎士藍斯洛特是一個騎士。

;可以寫作

Human lancelot = new Kinght();// 模糊宣告藍斯洛特為一個騎士,口語說法:人類藍斯洛特是一個騎士。

,上面這一行就是模糊化寫法,等號左邊只說了藍斯洛是人類,右邊才宣告了他是騎士;除此之外還可以寫作

var lancelot = new Kinght();

。無論上面哪一種寫法所產生出來的物件,都可以使用子類別中的方法,只是模糊寫法的物件在使用子類別的方法時,該物件必須強制轉型。

  再來是過載特性的複習,在一個類別中,有複數個成員方法的名稱相同,但其需要的參數屬性或數量的不同,JAVA 可以自動依所傳的參數判斷要使用哪一個方法,這個特性稱之為過載。

  JAVA 多型正是用到了模糊化寫法,而且擁有過載的特性。

  宣告一個父類別,父類別中擁有它自己的方法,然後其子類別中也有同名的方法,覆寫掉父類別中的同名方法;在主程式中定義的方法指定丟入參數為父類別的物件,但實際上你可以丟入任何有繼承該父類別的子類別所產生的物件,這就是模糊化;而 JAVA 會自動使用該物件在子類別中的同名方法,這就是過載。以下是 Elton 教我多型概念時的範例。

父類別:Shape 形狀,包含了一個它自己的方法 area 面積;

public class Shape {
public double area() {
return 0;
}
}

子類別:Circle 圓形,包含了和父類別同名的方法 area 面積;

public class Circle extends Shape {
int r;
double pi = 3.1415926;

public int getR() {
return r;
}

public void setR(int r) {
this.r = r;
}

public double getPi() {
return pi;
}

public void setPi(double pi) {
this.pi = pi;
}

public double area() {
return pi*r*r;
}

}

子類別:Rectangle 矩形,包含了和父類別同名的方法 area 面積;

public class Rectangle extends Shape {
int length;
int width;

public int getLength() {
return length;
}

public void setLength(int length) {
this.length = length;
}

public int getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}

public double area() {
return length * width;
}

}

主程式:裡面示範了方法的過載和多型兩種方式,註解應該算詳細,所以這裡不再說明。

public class Main {

// 以下是方法的多載(overloading),方法名稱相同,會依傳入的參數型別或數量不同而區別使用哪一方法。
// 萬一今天有多個不同的形狀,例如三角形,梯形,六角形等。下方就要為特定的形狀再多加宣告多組的面積方法,有些繁瑣。
public static double calArea(Circle cir) {
return cir.area();
}

public static double calArea(Rectangle rec) {
return rec.area();
}

// 那麼為了有更簡潔的方式,我們可以使用到多型的觀念。只宣告一組面積方法來算所有形狀的面積。
// 設定承接物件為父類別,模糊化所承接之物。
public static double calAreaBetter(Shape sha) {
return sha.area();
}

public static void main(String[] args) {
Circle cir1 = new Circle();
cir1.setR(12);

Rectangle rec1 = new Rectangle();
rec1.setLength(5);
rec1.setWidth(10);

double cirArea = calArea(cir1);
double recArea = calArea(rec1);
System.out.println("this is an area of circle by cir method:" + cirArea);
System.out.println("this is an area of rectangle by rec method:" + recArea);

cirArea = calAreaBetter(cir1);
recArea = calAreaBetter(rec1);
System.out.println("this is an area of circle by better method:" + cirArea);
System.out.println("this is an area of rectangle by better method:" + recArea);
}
}

結果:不管是用方法的過載或是多型的概念,都得到同樣的面積值。

this is an area of circle by cir method:452.38933440000005
this is an area of rectangle by rec method:50.0
this is an area of circle by better method:452.38933440000005
this is an area of rectangle by better method:50.0

Process finished with exit code 0

這個範例中的父類別是一般的類別,但我買的書,其範例是用抽象類別當父類別,或是用介面讓不同的類別實作,來完成多型的目的,其使用是自由自在的,下一篇會再練習一次多型,應該也是最後一篇物件導向的概念文章了,之後會練習如何使用套件與檔案處理。