Java的繼承概念上是很簡單的一件事,子類別會拿到父類別的屬性(field)跟方法(method),利用繼承簡化你的設計,可以在父類別上設計共同使用的屬性跟方法,子類別可以方便的繼承。
我們舉個例子,例如我有以下兩個類別簡單的類別Product 跟 DiscountProduct
public class Product {
String name;
int price;
public Product() {
}
public Product(String name, int price) {
this.name = name;
this.price = price;
}
public int getPrice() {
return price;
}
}
public class DiscountProduct {
String name;
int price;
double discount;
public DiscountProduct(String name, int price, double discount) {
this.name = name;
this.price = price;
this.discount = discount;
}
}
我們發現這兩個類別實際上是可以利用繼承來設計,因為DiscountProduct很明顯可以繼承Product,來獲得Product上的name屬性跟price屬性,簡化我們的設計
在繼承了Product後,我們可以拿掉name price屬性

接下來進行簡單的測試,程式中我們可以很清楚的知道目前DiscountProduct程式碼中沒有name跟price屬性,但因為繼承,所以自動有了父類別給予的屬性 name跟price 以及方法getPrice()
DiscountProduct discountProduct = new DiscountProduct("西瓜",100, 0.8);
System.out.println("name = " + discountProduct.name);//繼承來的屬性
System.out.println(discountProduct.getPrice());//繼承來的方法
結果如下:
name = 西瓜
80
這裏有三件事要注意
第一個是子類別上的重複的屬性要拿掉,如果子類別name price跟父類別重複卻沒有移除,會發生什麼事呢?假設我沒有拿掉name price
public class DiscountProduct extends Product{
String name;//保留
int price;//保留
double discount;
....
利用eclipse debug 一下 DiscountProduct discountProduct = new DiscountProduct(...)後,在variable中的情況

可以看到會有兩組name price出現在屬性中,這兩組name price,一組是DiscountPrirce自己的(屬性值為西瓜,100),另一組則是繼承至Product來的(屬性值為null跟0)。所以在繼承過程中,請記得把子類別中重複的屬性拿掉。
Intellj IDEA中透過debug則可以更明顯看到這個現象

那在這個例子中我要如何利用程式中區分這兩組屬性呢,你可以使用this.name(西瓜) this.price(100),而繼承來的就會是super.name(null) super.price(0),如下方範例toString(),當然實務上我們通常是不會有這種需求,大多情況下只要避免發生這情況就可以了
public class DiscountProduct extends Product {
String name;
int price;
...
@Override
public String toString() {
String info = String.format("this.name: %s, this.price: %d, Super.name: %s ,Super.price: %d Discount: %.2f",
this.name, this.price, super.name,super.price, discount);//利用this跟super區分兩組屬性
return info;
}
}
第二點我們要留意的是,子類別並不會自動繼承父類別的constructor,以下方的例子來說,雖然父類別有public Product(String name, int price),但這並不屬性繼承的範圍,所以你也只能使用 DiscountProduct中有定義的constructor
DiscountProduct dp2 = new DiscountProduct("西瓜",100); // compile會有錯
第三件事情是,子類別的constructor「一定」會呼叫父類別的constructor,在一般預設沒有特別呼叫的情況下會自動呼叫super()
public class DiscountProduct extends Product {
double discount;
public DiscountProduct(String name, int price, double discount) {
super();//這行不用寫,compile會自動幫你加
this.name = name;
this.price = price;
this.discount = discount;
}
另一種就是直接註明呼叫父類別super(name,price),所以即便沒有特別註明,父類別的constructor還是會被呼叫的。
public DiscountProduct(String name, int price, double discount) {
super(name,price);
this.name = name; //可省略,因為super(name,price)有執行相對應的程式
this.price = price;//可省略,因為super(name,price)有執行相對應的程式
this.discount = discount;
}
以上的情況再搭配this()可以變得更複雜,在這裏就不再詳加展示,如果有興趣的可以在下方留言,我再找時間補上。