多態
指的是一個引用型別
使用super class
,但是contructor
(構造器)使用sub class
多態只著重在方法
的部分,屬性
是沒有多態
的。
也可以稱做sub class
物件的多態性。
class Person {
String name;
public void eat() {
System.out.println("Person need eat.");
}
}
class Man extends Person {
// method override
public void eat() {
System.out.println("Man eat a lots of meat");
}
}
public class PersonTest {
public static void main(String[] args) {
// sub class object多態性
Person person = new Man();
person.eat(); // Man eat a lots of meat
}
}
super class
: Person
sub class
: Man
Person person = new Man();
編譯時會認為person
的方法是看Person
class
,但是當實際調用時會調用Man
class
中的方法。
super class
& sub class
override
)當使用多態性
的方式去宣告一個物件時,不能使用一般的方式去使用在sub class
中所宣告特有
的屬性
或方法
。
使用強制類型轉換
的方式,可以讓使用多態
的sub class
調用sub class
中特有的屬性
或方法
。
例如:
class Person {
String name;
public void eat() {
System.out.println("Person need eat.");
}
}
class Man extends Person {
double height;
// method override
public void eat() {
System.out.println("Man eat a lots of meat");
}
public void drink() {
System.out.println("Man drink water");
}
}
class Child extends Person {
}
public class PersonTest {
public static void main(String[] args) {
// sub class object多態性
Person person = new Man();
person.eat(); // Man eat a lots of meat
// 會錯誤
// person.height;
// person.drink();
Man man = (Man) person;
//可以正常使用
person.height;
person.drink();
Person person1 = new Child();
Man child = (Man) person1;
// 會錯誤 ClassCastException
// child.height;
// child.drink();
}
}
這邊可以看到有2個地方註釋起來並寫上會錯誤
person.height
:
類型
宣告為Person
了,所以是無法直接去使用在Man
中宣告的屬性
和方法
。強制類型轉換
的方式去將person
轉換並賦值,如上面的Man man = (Man) person;
。person
紀錄的是一個在Heap
中的位址值
,所以當這樣宣告時,man
所存的值也是和person
紀錄相同的位址值
。(之前在陣列
中有提到過,如果賦值的是非
基本數據類型時,都只是記錄存放在Heap
中的位址值
,當Heap
中的值更改時,因為變數的值
都是指向同一個地方,不管使用哪一個變數去查值時,結果都是去找該位址值中的值)child.height
:
Person
是Man
的super class
,所以它不會出現錯誤。Man
和Child
沒有任何關係,所以會出現ClassCastException
(類型轉換異常)。如果要在這樣的情況下去使用時,建議使用instanceOf
先進行判斷,確定沒問題了再去做強制類型轉換的動作。
class Person {
String name;
public void eat() {
System.out.println("Person need eat.");
}
}
class Man extends Person {
double height;
// method override
public void eat() {
System.out.println("Man eat a lots of meat");
}
public void drink() {
System.out.println("Man drink water");
}
}
class Child extends Person {
}
public class PersonTest {
public static void main(String[] args) {
// sub class object多態性
Person person = new Man();
person.eat(); // Man eat a lots of meat
// 會錯誤
// person.height;
// person.drink();
if(person instanceOf Man) {
Man man = (Man) person;
//可以正常使用
person.height;
person.drink();
}
Person person1 = new Child();
// always false, because person1 not Child sub class
if(person1 instanceOf Child) {
Man child = (Man) person1;
}
if(person1 instanceOf Child) {
Child child = (Child) person1;
System.out.println("我成功轉換了") //我成功轉換了
}
}
}
💡 "a instaceOf b":指的是問 "a" 是否為 "b" 的 "sub class",會返回一個 "true" 或 "false"。
💡
"a instanceOf b" > "true"
"a instanceOf superb" > "true"
"b is superb's sub class"
class Transportation {
public void speed() {
System.out.println("transpertation speed.");
}
}
class Train extends Transportation {
public void speed() {
System.out.println("The train speed is 60 kilometers");
}
}
class HighSpeedRail extends Transportation {
public void speed() {
System.out.println("The HighSpeedRail speed is 260 kilometers");
}
}
public class TransportationTest {
public static void main(String[] args) {
TransportationTest test = new TransportationTest();
Transportation train = new Train();
Transportation highSpeedRail= new HighSpeedRail();
test.currentSpeed(train); //The train speed is 60 kilometers
test.currentSpeed(highSpeedRail); //The HighSpeedRail speed is 260 kilometers
}
public void currentSpeed(Transportation transportation) {
transportation.speed();
}
}
當使用多態性
時,可以使擴充性
更好,例如public void currentSpeed(Transportation transportation)
,由於使用多態性
的關係,Java會自動去找尋對應的sub class
中,是否有重寫的方法,若沒有則會去調用super class
中的方法,並且這樣的方式也可以減少很多重複的程式碼。
例如:沒有使用多態性的情況
public class TransportationTest {
public static void main(String[] args) {
TransportationTest test = new TransportationTest();
Train train = new Train();
HighSpeedRail highSpeedRail= new HighSpeedRail();
test.currentSpeed(train); //The train speed is 60 kilometers
test.currentSpeed(highSpeedRail); //The HighSpeedRail speed is 260 kilometers
}
public void currentSpeed(Train train) {
train.speed();
}
public void currentSpeed(HighSpeedRail highSpeedRail) {
highSpeedRail.speed();
}
}
必須要依照不同的類別去寫不同的方法,由於範例中只有兩個sub class
,所以看起好像有點雞肋,但是當sub class
多了起來後,使用多態性
的好處和優點就能夠漸漸浮現出來,並且當有新增的sub class
時,也不必再特別為了這個sub class
增加新的方法。