重新定義實作
文章推薦指數: 80 %
對 drawFight() 方法而言,只知道傳進來的會是一種 Role 物件,所以編譯器也只能檢查你呼叫的方法, Role 是不是有定義,顯然地, Role 目前並沒有定義 fight() 方法, ...
回Java目錄
現在有個需求,請設計static方法,可以播放角色攻擊動畫,你也許會這麼想,學剛剛多型的寫法,設計個drawFight()方法如何?
對drawFight()方法而言,只知道傳進來的會是一種Role物件,所以編譯器也只能檢查你呼叫的方法,Role是不是有定義,顯然地,Role目前並沒有定義fight()方法,因此編譯錯誤了。
然而你仔細觀察一下SwordsMan與Magician的fight()方法,他們的方法簽署(methodsignature)都是:
publicvoidfight()
也就是說,操作介面是相同的,只是方法實作內容不同,你可以將fight()方法提昇至Role類別中定義:
packagecc.openhome;
publicclassRole{
...略
publicvoidfight(){
//子類別要重新定義fight()的實際行為
}
}
在Role類別中定義了fight()方法,由於實際上角色如何攻擊,只有子類別才知道,所以這邊的fight()方法內容是空的,沒有任何程式碼實作。
SwordsMan繼承Role之後,再對fight()的實作進行定義:
packagecc.openhome;
publicclassSwordsManextendsRole{
publicvoidfight(){
System.out.println("揮劍攻擊");
}
}
在繼承父類別之後,定義與父類別中相同的方法簽署,但實作內容不同,這稱為重新定義(Override),因為對父類別中已定義的方法實作不滿意,所以你在子類別中重新定義實作。
Magician繼承Role之後,也重新定義了fight()的行為:
packagecc.openhome;
publicclassMagicianextendsRole{
publicvoidfight(){
System.out.println("魔法攻擊");
}
...略
}
由於Role現在定義了fight()方法(雖然方法區塊中沒有程式碼實作),所以編譯器不會找不到Role的fight()了,因此你可以如下撰寫:
packagecc.openhome;
publicclassRPG{
publicstaticvoidmain(String[]args){
SwordsManswordsMan=newSwordsMan();
swordsMan.setName("Justin");
swordsMan.setLevel(1);
swordsMan.setBlood(200);
Magicianmagician=newMagician();
magician.setName("Monica");
magician.setLevel(1);
magician.setBlood(100);
drawFight(swordsMan);
drawFight(magician);
}
staticvoiddrawFight(Rolerole){
System.out.print(role.getName());
role.fight();
}
}
在fight()方法宣告了Role型態的參數,那方法中呼叫的,到底是Role中定義的fight(),還是個別子類別中定義的fight()呢?如果傳入fight()的是SwordsMan,role參數參考的就是SwordsMan實例,操作的就是SwordsMan上的方法定義。
這就好比role牌子掛在SwordsMan實例身上,你要求有role牌子的物件攻擊,發動攻擊的物件就是SwordsMan實例。
同樣地,如果傳入fight()的是Magician,role參數參考的就是Magician實例,操作的就是Magician上的方法定義。
所以範例最後的執行結果是:
Justin揮劍攻擊
Monica魔法攻擊
在重新定義父類別中某個方法時,子類別必須撰寫與父類別方法中相同的簽署,然而如果疏忽打錯字了:
publicclassSwordsManextendsRole{
publicvoidFight(){
System.out.println("揮劍攻擊");
}
}
以這邊的例子來說,父類別中定義的是fight(),但子類別中定義了Fight(),這就不是重新定義fight()了,而是子類別新定義了一個Fight()方法,這是合法的方法定義,編譯器並不會發出任何錯誤訊息,你只會在運行範例時,發現為什麼SwordsMan完全沒有攻擊。
在JDK5之後支援標註(Annotation),其中一個內建的標準標註就是@Override,如果你在子類別中某個方法前標註@Override,表示要求編譯器檢查,該方法是不是真的重新定義了父類別中某個方法,如果不是的話,就會引發編譯錯誤。
例如:
延伸文章資訊
- 1重新定義實作
對 drawFight() 方法而言,只知道傳進來的會是一種 Role 物件,所以編譯器也只能檢查你呼叫的方法, Role 是不是有定義,顯然地, Role 目前並沒有定義 fight() 方法...
- 2方法_百度百科
方法是一個漢語詞彙,方法的含義較廣泛,一般是指為獲得某種東西或達到某種目的而採取的手段與行為方式。方法在哲學,科學及生活中有着不同的解釋與定義。
- 3定義方法_百度百科
定義方法是揭示概念內涵的邏輯方法。通過某概念所反映的對象的本質屬性來説明該概念。從邏輯結構上看,定義包括三個部分:①被定義項,即其內涵需要明確的概念;②定義 ...
- 4方法定義- JavaScript
自ECMAScript 2015 開始,引入了一種於物件初始器(objects initializers)中定義方法的簡短語法。是一個將函式指派予方法名稱的簡便方式。
- 5什麼方法? 方法:定義 - ad
方法:定義. 幾乎每個人的詞彙出現幾千字。 這個數字基本上取決於他的教育,博學,共同發展的水平。 據統計,成人詞彙的平均日成交量為內十一時五十千言萬語。