第15節 - @Override的用法和意思
這一節我會介紹@Override Annotation,@Override是Java的特殊功能,稱為Annotation,Annotation是給編譯器(Compiler)看的提示。
因為Java是一種物件導向程式語言,只要一個子類別(Child)繼承(extends)父類別(Parent),父類別和子類別就有一個@Override的關係。
@Override就是告訴編譯器以下子類別的方法是和父類別的方法(串法)完全一樣(e.g. create()),但子類別想要重新定義內容,請幫忙確定一下子類別的方法(串法)是否和父類別的方法完全一樣,如果不一樣就會發出錯誤信息。
簡單來說,@Override就有檢查子類別方法的串法和父類別方法的串法是否一樣的功能。
注意,如果我們沒有打錯子類別的方法,@Override不是必須的,不過見意大家習慣去用@Override。
以上就是LibGDX預設的第一個程式。
- 子類別(MyDemo15)的create()方法要重新定義,@Override就是檢查MyDemo15的create()方法是否和父類別(ApplicationAdapter)的create()方法完全一樣。
- 子類別(MyDemo15)的render()方法要重新定義,@Override就是檢查MyDemo15的render()方法是否和父類別(ApplicationAdapter)的render()方法完全一樣。
注意,小寫create()和大寫Create()是不同的,如果串錯大寫Create(),@Override會發出錯誤信息。
例子1 - 用我們第一個MyDemo15 Class繼承ApplicationAdapter abstract Class
當我們建立第一個LibGDX的Class,例如:MyDemo15,LibGDX預設把MyDemo15繼承ApplicationAdapter,而ApplicationAdapter 實作(implements) ApplicationListener介面,如下圖:
- ApplicationAdapter implements ApplicationListener
- MyDemo15 extends ApplicationAdapter
LibGDX官方文件 - ApplicationAdapter.java Class
- 在LibGDX官方文件ApplicationAdapter.java內可以看到ApplicationAdapter實作ApplicatonListener interface。
- 用ApplicationAdapter的原因是ApplicationAdapter內已經把所有ApplicationListener內的抽象方法定義了內容。
ApplicationListener內的public void create(); 就是抽象方法,則是內容沒有{......}的。
ApplicationAdapter內的public void create(){ }; 就是定義了內容方法,則是內容有{......}的。
注意,就算{ }內是空白沒有內容,只要有{ }就代表定義了內容方法。
LibGDX官方文件 - ApplicationListener.java interface
- ApplicationListener是一個介面(interface)。
- ApplicationListener內的所有方法都是抽象方法,例如: public void create(); 就是抽象方法,則是內容沒有{......}的。
LibGDX - 我們的第一個程式MyDemo15.java Class
- 因為create()已經在ApplicationAdapter內定義了內容,create()在MyDemo15內可以覆寫或不覆寫。
- 和create()一樣,因為render()已經在ApplicationAdapter內定義了內容,render()在MyDemo15內可以覆寫或不覆寫。
ApplicationAdapter, ApplicationListener和MyDemo15的方法(method)運用和比較
以下就把ApplicationAdapter, ApplicationListener和MyDemo15的方法(method)作比較:
- ApplicationListener是一個interface,所有方法必須是抽象方法,則是內容沒有{......}的。
- ApplicationAdapter是一個abstract class,它已經把所有方法定義了內容,則是內容有{......}的,其後繼承它的類別就可以覆寫或不覆寫。
注意,如果在abstract class內還沒有定義內容,其後繼承它的類別就必須覆寫方法。
- MyDemo15是一個類別,所有方法可以覆寫或不覆寫,以上例子就只覆寫了create()和render()方法。
注意,如果在abstract class內還沒有定義內容,其後繼承它的類別就必須覆寫方法,詳細介紹請看例子3。
例子2 - 用我們第一個MyDemo15 Class直接實作ApplicationListener interface
假設我們不用ApplicationAdapter,而把MyDemo15 Class直接實作ApplicationListener interface,看看和例子1有甚麼分別,如下圖:
- 把MyDemo15 Class直接實作ApplicationListener interface。
LibGDX官方文件 - ApplicationListener.java interface
- ApplicationListener是一個介面(interface)。
- ApplicationListener內的所有方法都是抽象方法,例如: public void create(); 就是抽象方法,則是內容沒有{......}的。
LibGDX - 我們的第一個程式MyDemo15.java Class
- 把MyDemo15 Class直接實作ApplicationListener interface。
- 因為MyDemo15是一個Class (不是abstract class),所以實作ApplicationListener interface後必須把所有方法定義了內容,則是內容有{......}的。
注意,就算{ }內是空白沒有內容,只要有{ }就代表定義了內容方法。
ApplicationListener和MyDemo15的方法(method)運用和比較
以下就把ApplicationListener和MyDemo15的方法(method)作比較:
- ApplicationListener是一個interface,所有方法必須是抽象方法,則是內容沒有{......}的。
- 因為MyDemo15是一個Class (不是abstract class),所以實作ApplicationListener interface後必須把所有方法定義了內容,則是內容有{......}的。
例子3 - 用我們第一個MyDemo15 Class繼承Game Class
例子3就是我們會用來寫LibGDX遊戲程式的種類,把我們的MyDemo15繼承LibGDX的Game類別,再把Game類別實作(implements) ApplicationListener介面,如下圖:
- 我們會用到LibGDX的Game類別,這是因為Game類別內有一個setScreen()方法,它可以用來轉換畫面,例如在第17節 - LibGDX: Splash Screen用來做過埸畫面。
- 再把Game類別實作(implements) ApplicationListener介面。
LibGDX官方文件 - Game.java abstract class
- 在LibGDX官方文件Game.java內可以看到Game實作ApplicatonListener interface。
- 除了create()方法尚未定義了內容外,其他所有方法已經定義了內容。
注意,要做到有些方法定義了內容,有些方法不定義內容(例如: create()方法),我們必須用abstract class。
還有,就因為create()方法尚未在Game內定義內容,我們必須在MyDemo15類別內定義內容。
LibGDX官方文件 - ApplicationListener.java interface
- ApplicationListener是一個介面(interface)。
- ApplicationListener內的所有方法都是抽象方法,例如: public void create(); 就是抽象方法,則是內容沒有{......}的。
如果在MyDemo15 Class內沒有實作create()方法
- 把MyDemo15 Class繼承Game abstract Class。
固意不定義create()方法的內容,就會發出錯誤信息。
如果在MyDemo15 Class實作create()方法
- 把MyDemo15 Class繼承Game abstract Class。
- 這次定義create()方法的內容,錯誤信息就會消失。
- 注意,因為所有resize(), render(), pause(), resume()和dispose()在Game類別內都定義了內容,除了在MyDemo15類別內覆寫這些方法外,我們必須在resize(), render(), pause(), resume()和dispose()方法內執行"super",例如:super.render();就是執行父類的render()方法(則game.render();),這樣做就能夠確保Game類別內定立的方法在MyDemo15類別內也有執行。
雖然現在沒有把"super"放在MyDemo15類別內也不會出現錯誤信息,但將來執行程式時就有機會出現錯誤,尤其是如果我們在將來用到callbacks (則pause, resume等等)。
ApplicationListener,Game和MyDemo15的方法(method)運用和比較
以下就把ApplicationListener,Game和MyDemo15的方法(method)作比較:
- ApplicationListener是一個interface,所有方法必須是抽象方法,則是內容沒有{......}的,所以create()尚未定義。
在Game abstract class內create()也未定義內容,所以在MyDemo15 class內必須定義內容。 - 在Game abstract class內resize(), render(), pause(), resume()和dispose()已經定義了內容,所以在MyDemo15 class內可以覆寫或不覆寫,以上例子就覆寫所有resize(), render(), pause(), resume()和dispose()方法。
- 最後,我們用MyDemo15 class 繼承Game abstract class是因為Game內有兩個新方法:
setScreen(Screen screen);
getScreen(Screen screen);
setScreen()方法可以用來轉換畫面,例如在第17節 - LibGDX: Splash Screen我們會介紹過埸畫面(Splash Screen)的做法。