5.4 Given a scenario, develop code that declares and/or invokes overridden or overloaded methods and code that declares and/or invokes superclass, overridden, or overloaded constructors.
Overriding method(覆寫函式)
class Animal { public void move() { System.out.println("Animals can move"); } } class Dog extends Animal { public void move() { System.out.println("Dogs can walk and run"); } }上述範例中Dog override move(),針對非abstract class可以選擇要不要override,但是如果superclass有abstract class,則一定要override,除非該subclass也是abstract class。否則若是concrete class則一定需要override。
以下為一polymorphism範例
public class TestDog { public static void main(String args[]) { Animal a = new Animal(); // Animal reference and object Animal b = new Dog(); // Animal reference but Dog object a.move(); // runs the method in Animal class b.move(); // runs the method in Dog class } }
- 編譯器只允許呼叫reference variable type內擁有的method。polymorphism的功能在於,可以使用superclass的variable reference,指到subclass的object,甚至使用被override的method。
- 如上節所說,JVM會去呼叫該object的真實型別看看method有沒有被override,若有,就會使用。
- overriding method不能擁有比原method更侷限的access modifier (ex: public -> protected)
說個故事:有一天電器Class(Appliances Class)宣稱可以藉由extends該Class取得賣出價格method(sellPrice()),但今天冰箱(Refrigerator Class) extends 後把sellPrice()繼承了而且偷改access modifier變成private,則以下範例將會有問題:
Appliances rg = new Refrigerator(); //object type: Refrigerator, reference type: Appliances rg.sellPrice(); // runs the method in Refrigerator class 此行會爆炸
- 讓superclass的reference variable可以指到subclass object的原因是,subclass可以保證能夠做得到所以superclass能夠做到的事情
- 為了達到不管reference variable今天指到的object type是何者,都要能夠保證能夠使用原本reference variable type可以呼叫的method,因此有以下幾點規範
- overriding method不能擁有比original method更侷限的access modifier,但可以更鬆散
- overriding method的parameters必須和original method的相同,如果不同就不叫做overriding,只是寫了一個新的method
- overriding method的return type必須和original method的相同,或者是subtype (covariant return)
- 只有當instance method有被subclass extends的時候才可以做overriding。意即,一個private,final,static的method都不能夠被overriding
- 不論original method是否有宣告exception,overriding method可以拋出runtime exception(unchecked exception)
- overriding method不能夠拋出新的checked exception,異常範圍也不可以更廣
- 不論original method宣告了些異常,overriding method不需要宣告任何它不會拋出的exception。
- 不能override final or static method
- 若想要在override之前先執行original method做的事情,則需要用到keyword(super)
public class FlyingCar extends Car{ public int startEngine(EncryptedKey key) { super.startEngine();//先執行super class Car裡面的startEngine method //繼續做FlyingCar想ㄧ做的事情 } }
Overload method(多載函式)
- Overload規則如下:
- 必須變更parameter
- 可以變更return type
- 可以變更access modifier
- 可以宣告新的或範圍更廣的checked exception
- 可以在subclass和superclass間發生。例如superclass的method: getHeight();而subclass繼承後不改寫superClass的getHeight(),另外寫了一個method: getHeight(int years),這樣也叫做overload
呼叫Overloading method
class TestAnimal { public void doStuff(Animal am){ System.out.println("Animal"); } public void doStuff(Cat cat){ System.out.println("Cat"); } public static void main (String args []) { TestAnimal ta = new TestAnimal(); Animal am = new Animal(); Animal cat = new Cat(); ta.doStuff(am); //print "Animal" ta.doStuff(cat); //print "Cat" } }
注意上述範例,最後ta.doStuff(cat)執行的是public void doStuff(Cat cat)這個method!
在runtime時雖然知道了這個object的真實type,並不會再runtime的時候被動態的決定要呼叫哪個overloading method。
總結
- override: 根據runtime時的object type決定要執行哪一個method。
- overload: 根據compile時被傳入當作overloading method內argument的variable reference type來決定的。
Override and Overload
Polymorphism並不會影響哪個override的method會被呼叫。Method可以同時被Overload及Override,如下面的範例:class Animal{ void eat(){ System.out.println("Animal eats"); } } class Cat extends Animal{ void eat(){ System.out.println("Cat eats"); } void eat(String mood){ System.out.println("Cat has mood of eat : " + mood); } } class TestAnimal{ public static void main (String args []){ Animal a = new Animal(); a.eat(); //print "Animal eats" Cat c = new Cat(); c.eat(); //print "Cat eats" Animal am = new Cat(); am.eat(); //print "Cat eats" Cat ct = new Cat(); ct.eat("Happy"); //print "Cat has mood of eat : Happy" Animal am2 = new Animal(); am2.eat("Excited"); //Compile error! Animal內沒有argument為String的eat method Animal am3 = new Cat(); am3.eat("Sad"); //Compile error! 雖然此行是根據reference type(Cat)來決定要跑的method,但因為Animal沒有此method,所以編譯會直接錯誤 } }
注意每個Output。
沒有留言:
張貼留言