[Java] 14.3. 自訂泛型

打造支援泛型別的類別。

 

image/svg+xml14.3. ⾃訂泛型 – Custom Generic 假想下列程式是可⾏的: class Main{ public static void main( String [] args){ Room < Employee > r1 = new Room < Employee >(); Room < Dog > r2 = new Room < Dog >(); Room < Cat > r3 = new Room < Cat >(); } } import java.util.*; class Room < T >{ T manager; private List < T > emps = new ArrayList < T >(); boolean add( T e){ return emps.add(e); } T get( int index){ return emps.get(index); } boolean remove( T e){ return emps.remove(e); } int size(){ return emps.size(); } } import java.util.*; class Main{ public static void main( String [] args){ Room < Employee > r1 = new Room < Employee > (); r1.add ( new Employee ( "K12345678" , “Jack" , 20 , " 男⽣ " , "048679" , 40000 )); r1.add ( new Programmer ( "K00000000" , “Eric" , 25 , " 男⽣ " , "041121" , 45000 )); Room < Dog > r2 = new Room < Dog >(); r2.add ( new Dog ( "Coopy" )); Room < Cat > r3 = new Room < Cat >(); r3.add ( new Cat ( "Cookie" )); } } import java.util.*; class Main{ public static void main( String [] args){ Room < Employee > r1 = new Room < Employee >(); Room < Programmer > r2 = new Room < Programmer >(); Room < Tester > r3 = new Room < Tester >(); Room < Artist > r4 = new Room < Artist >(); Room < Dog > r5 = new Room < Dog >(); Room < Cat > r6 = new Room < Cat >(); } } import java.util.*; class Room < T extends Employee >{ T manager; private List < T > emps = new ArrayList < T >(); boolean add( T e){ return emps.add(e); } T get( int index){ return emps.get(index); } boolean remove( T e){ return emps.remove(e); } int size(){ return emps.size(); } } import java.util.*; class Main{ public static void main( String [] args){ Room < Employee > r1 = new Room < Employee >(); Room < Programmer > r2 = new Room < Programmer >(); Room < Tester > r3 = new Room < Tester >(); Room < Artist > r4 = new Room < Artist >(); Room < Dog > r5 = new Room < Dog >(); Room < Cat > r6 = new Room < Cat >(); } } 執⾏結果 Main.java:11: error: type argument Dog is not within bounds of type- variable T Room<Dog> r5 = new Room<Dog> (); ^ where T is a type-variable: T extends Employee declared in class Room Main.java:11: error: type argument Dog is not within bounds of type- variable T Room<Dog> r5 = new Room<Dog> (); ^ where T is a type-variable: T extends Employee declared in class Room Main.java:12: error: type argument Cat is not within bounds of type- variable T Room<Cat> r6 = new Room<Cat> (); ^ where T is a type-variable: T extends Employee declared in class Room Main.java:12: error: type argument Cat is not within bounds of type- variable T Room<Cat> r6 = new Room<Cat> (); ^ where T is a type-variable: T extends Employee declared in class Room 4 errors class Employee extends Person{ String employeeID; int salary; void show (){ System.out.println( " 員⼯編號是 " + employeeID); System.out.println( " 薪資是 " + salary); } // 略過⼀些程式 } class Programmer extends Employee{ void show (){ System.out.println( " 我是程式設計師 " ); super .show(); } // 略過⼀些程式 } class Artist extends Employee{ void show (){ System.out.println( " 我是美⼯⼈員 " ); super .show(); } // 略過⼀些程式 } class Tester extends Employee{ void show (){ System.out.println( " 我是測試⼈員 " ); super .show(); } // 略過⼀些程式 } import java.util.*; class Room < T extends Employee >{ // 略過⼀些程式 < X extends Employee > X training ( X trainer ){ trainer.show (); System.out.println( " 現在幫⼤家進⾏內部訓練。 " ); return trainer; } } import java.util.*; class Main{ public static void main( String [] args){ Room < Employee > r1 = new Room < Employee >(); Employee e1 = new Employee ( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee ( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 ); r1 .add( e1 ); r1 .add( e2 ); Programmer p1 = new Programmer ( “K11111111" , "Mary" , 18 , " 女⽣ " , "050021" , 30000 ); r1. training ( p1 ); Tester t1 = new Tester ( "K22222222" , "Jack" , 19 , " 男⽣ " , "051212" , 42000 ); r1. training ( t1 ); } } 執⾏結果 我是程式設計師 員⼯編號是 050021 薪資是 30000 現在幫⼤家進⾏內部訓練。 我是測試⼈員 員⼯編號是 051212 薪資是 42000 現在幫⼤家進⾏內部訓練。 1. 使⽤泛型,限制這個房間是 員⼯( Employee )專⽤的 2. 使⽤泛型,限制這個房間是狗( Dog )專⽤的 3. 使⽤泛型,限制這個房間是貓( Cat )專⽤的 嗯,這樣通⽤⼜有限制的模式⽅式很棒,好⽤。 4. 但前題是如何讓房間類別 Room )⽀援泛型的功能呢? J14_3_1 Room.java 1. 房間類別( Room )若要⽀援泛型的功能,這時候就必須在類 別的後⾯加上⼀對箭號( <> ),並在箭號中加上泛型參數,當然 參數就像是變數⼀樣,名稱是由我們⾃已決定的,不同於以往的參 數的地⽅在於泛型變數將的是型別,並不是資料或物件。 2. 可以作為 屬性的型別。 3. 可以作為泛型的型別。 4. 可以作為參數的型別。 5. 可以作為回 傳值的型別。 6. 在這個房間類別中,我們利⽤到 List 集合作為 保存物件的集合,以簡單的模擬員⼯進出的狀況。 7. 再次作為參數的型別。 若有兩個以上的泛型參數時,可以使⽤逗號( , )將泛型參數隔開,例如 <T1, T2> ,這樣就可以在同⼀個類別中擁有兩個以上的泛型參數。 J14_3_1 Main.java 1. 使⽤泛型,限制這個房間( Room )是員⼯( Employee )專⽤的 2. 沒問題,加入 2 個員⼯型別( Employee )的物件 (程式設計師類別( Programmer )繼承⾃員⼯類別)。 3. 使⽤泛型,限制這個房間是狗( Dog )專⽤的 5. 使⽤泛型,限制這個房間是貓( Cat )專⽤的 4. 沒問題,加入阿狗物件( Dog )⾄泛型型別為阿狗的集合中。 6. 沒問題,加入阿貓物件( Cat )⾄泛型型別為阿貓的集合中。 J14_3_2 Main.java 1. 只能建立員⼯( Employee )專⽤的房間。當然這也包括繼承⾃員⼯類別的程式設計 師類別、測試⼈員類別與美⼯⼈員類別( Programmer Tester Artist )。 2. 希望能夠防⽌建立非員⼯專⽤的房間,怎麼辦? J14_3_3 Room.java 2. 在泛型參數後加上 extends ,接著是員⼯類別 Employee )的型別,這樣就會限制泛型參數所接收 的型別,必須是員⼯類別或是繼承⾃員⼯類別的型別。 當在宣告房間變數或是建立房間物件時,就只有員⼯型 別或繼承員⼯的型別可作為泛型型別。 1. 這是房間類別( Room )。 J14_3_3 Main.java 1. 因房間類別使⽤了 <T extends Employee> 定義泛型變數,因此能夠作為房間物件的泛型只可以 是員⼯( Employee )或是繼承⾃員⼯的⼦類別。 2. 當建立非員⼯專⽤的房間時,這時編譯器會發⽣錯誤,告訴您不能建立狗( Dog )與 貓( Cat )專屬的房間,因為狗與貓並不是房間類別所能接受的泛型型別,原因即出在狗 與貓類別並沒有與員⼯類別有繼承的關係,因此狗與貓類別並不是員⼯類別的⼀種。 J14_3_4 Employee.java J14_3_4 Main.java J14_3_4 Ar : st.java J14_3_4 Tester.java J14_3_4 Programmer.java 1. 員⼯有個⾃我介紹⽅法 show() ,進⾏⾃我介 紹,程式設計師 Programmer 、美⼯⼈員 Artist 測試⼈員 Tester 分別改寫以介紹⾃已的⾝份為何。 J14_3_4 Room.java 5. 因為訓練⽅法擁有不同的泛型,如此就可以派 不同類型的員⼯給這個房間的員⼯做訓練,它可以 是員⼯、程式設計師、美⼯⼈員或測試⼈員。 2. 在此建立⼀個訓練 training() ⽅法。 4. 同樣的,這個泛型也可作為參數與回傳值的型 別,⼜或是其他可能⽤到型別的地⽅,比如變數。 8. 再次帶入⼀個測試⼈員 Tester 進⾏訓練, 泛型 X 會指定為 Tester ,這也是沒問題的。 3. 特別的是這個⽅法有個⾃已的泛型型別 X ,加在回傳值型別前,與房間 Room T 型是另⼀個泛型型別。 X 泛型同樣繼承⾃員 ⼯型別確保 X 的型別也是繼承⾃員⼯。 6. 建立兩個員⼯,並放入房間中,這時的房間限定只有員⼯才能進入。 7. 因為訓練⽅法 traing() 擁有獨立的泛型 X ,因為帶入參數時, 編譯器即會透過參數推論出這個 X 泛型是程式設計師 Programmer 如此就達到泛型型別不需與房間的泛型⼀致的需求。 打造⽀援泛型的房間類別,可以嗎? 使⽤箭號( <> )為房間類別加上泛型參數, 以存放泛型的型別 測試您⽀援泛型的房間 我不想建立阿貓阿狗也可以進入的房間, 這時要怎麼辦呢? 打造只有⼈員才可進出的房間,貓狗勿入 證明⼀下員⼯專屬的房間,只有員⼯可進入 1 2 1 2 訓練⽅法,也可以獨立擁有泛型型別 1 2 1 2

留言