polymorphism & Abstract Class
21 April 2020
OOP - polymorphism & Abstract class
讓derived class的methods changes apply到base class的method changes 利用late-binding給予一個method多種執行方法、意義
簡單來說就是為了Flexibility, base class可以有method, derived class能夠依據狀況把method的內容複寫
目的在於在開發時常常有物件應該屬於同類但因為些微的差距所以method要有調整,polymorphism就是在這種狀況下derived class能覆寫那些method符合自己的需求
Reference: medium
情境
定義一個base class跟一些共用method,但是之後又加了一個derived class C,而C其中繼承到的一個method A呼叫了C override的method B,但是method B本身是base class的method所以會隨著base class先compiled了,那Class C呼叫method A時很有可能錯誤,因為method B沒有隨著新的Class定義的method B而作出對應修改。
Late binding
late binding = dynamic binding
binding
某method的程式碼內呼叫其他method。
假設method是在compile時就跟呼叫的method做好連接 : early binding
假設method是在run time在跟呼叫的method做好連接 : late binding
Java幾乎都使用late binding,因此method A在呼叫method B時,是真的要呼叫時才做連接,不是編譯時就做連接
因此在object編譯好後,會有像dynamic link的感覺有記錄某個method要連到哪。
final
final method表示此method不能被override
final class代表該class不能當作base class
public final void someMethod(){} public final class someclass{}
宣告final的method或class可以用early binding,因為derived class也沒有機會改寫,增加compiler效率
toString polymorphism
所有的class都屬於object class,object class有自己的toString method,
因此在System.out.println(a)時都可以印出String,因為object class有定義好
但在我們自創的class中,我們可以自己寫一個toString的class,這樣System.out.println呼叫object toString時,會呼叫到自己定義的class(descendant class)的toString而不是呼叫object class的toString
no late binding
- final method
- private method
- static method
static method可以想像,因為static method不論多少object都只有一個,就是定義在base
class那個,每個object共用,問題在於如果static method呼叫了某個polymorphism的method
A,則method A會以base class的method A為主(static method所在的class,畢竟是以呼叫
該method的class: base class)而不是derived class
upcasting, downcasting
upcasting 子類別 type cast成父類別 downcasting 父類別 type cast成子類別
downcasting
downcasting很容易有error,因為子類別很多時候會有自己才有的variable,這時候downcast就會error,因此使用時要確保沒有這些事情發生才用downcast
B extends A A為B的父類別且B有一些A沒有的instance variable
A = (B)A -> run-time error
A = B -> compile error
instanceof
可以用instanceof來確定downcast能不能做(確定是不是同個class),同個class才能做
Object instanceof Class_name
Clone
每個自己定義的class都會從Object class繼承clone這個method,只是要自己override,就是做deep copy複製一份依樣的object。
protected Object clone()
----------------------- override
public Sale clone(){...(可以先用new, constructor的方式)}
把protected改成public,外面人才能呼叫
小注意
java 5.0以前的版本override不允許換return 的type,所以如果用以前的java版本來做clone完後要記得type cast成現在定義的class,java 5.0後也有可能出現這個問題(可能別人定義的clone沒改type)
所以最好方式是自己呼叫clone後在type cast一次保險
Sale copysale = (Sale)s.clone();
Copy constructor & clone差別 ???
要複製一個新的object,尤其在牽扯到父、子類別、polymorphism時要特別注意,盡量用clone。
我們知道子類別算是父類別的class,所以宣告是父類別為參數的函式可以傳子類別進去,如果複製時是用copy constructor,那就只會複製到該子類別object屬於父類別的部分,自己獨有的不會複製到,那這樣否些情況是不好的,如下:
Class : Sales->DiscountSale
a : DiscountSale
b : sale
public static Sale badcopy(Sale a){
Sale b = new Sale(a); // 此時身為object a獨有的東西不會複製給b
return b; // 假設a傳進去時是derived class DiscountSale
// 此時用copy constructor的話會呼叫Sale的constructor
// 而sale是base class,所以等於原本object a獨有的東西
// 就不會複製給b(因為是呼叫base class constructor)
// constructor當然不會定義derive class獨有東西的assign
}
public static Sale goodcopy(Sale a){
Sale b = a.clone(); // 此時身為object a獨有的東西才會複製給b
// 因為clone可以override,所以此時呼叫的clone是呼叫
// derive class的method,而不是呼叫到base class
// 的constructor,所以clone內部function可以把derive
// class獨有的東西傳給b。
return b;
}
Abstract class
沒有完整defined的class,不能create object,但可以用它來當作base class定義一些derived class,會定義一些abstract method。可以想成abstract class就是一種object type但是不能夠產生object, instance。
子類別要完整實做這些abstract method
- abstract method就是要給derived class實作,所以不能宣告private
- 沒有實做完abstract method的derived class也是abstract class,不能建立object
public abstract class AbstractCircle {
protected double radius;
public void setRedius(int radius) { this.radius = radius; }
public double getRadius() { return radius; }
public abstract void render();
}