[Java] 6.6. 抽象類別 張貼者: 羅康鴻 日期: 6月 29, 2021 取得連結 Facebook X Pinterest 以電子郵件傳送 其他應用程式 抽象,一種概念,它不可被創造。 image/svg+xml6.6. 抽象類別 - abstract class 第 1 步, abstract 抽象化員⼯類別 class Main { public static void main( String [] args){ Employee e = new Employee (); e.id = "k1234567890" ; e.name = "jack" ; e.gender = " 男 " ; e.setAge( 25 ); e.employeeID = "048679" ; e.salary = 40000 ; Programmer p = ( Programmer ) e ; Tester t = ( Tester ) e ; Artist a = ( Artist ) e ; } } 執⾏結果 Exception in thread "main" java.lang.ClassCastException: Employee cannot be cast to Programmer at Main.main(Main.java:11) abstract class Employee extends Person { String employeeID; int salary; void show (){ super .show(); System.out.println( " 員⼯編號是 " + employeeID); System.out.println( " 薪資是 " + salary); } double getBonus(){ return ( 0.1 * salary); } } class Main { public static void main( String [] args){ Employee e1 = new Programmer (); Employee e2 = new Tester (); Employee e3 = new Artist (); } } class Main { public static void main( String [] args){ Employee e1 = new Employee (); } } 編譯時發⽣錯誤 Main.java:3: error: Employee is abstract; cannot be instantiated Employee e1 = new Employee(); ^ 1 error abstract class Employee extends Person{ String employeeID; int salary; void show(){ super .show(); System.out.println( " 員⼯編號是 " + employeeID); System.out.println( " 薪資是 " + salary); } abstract double getBonus () ; } class Programmer extends Employee { // 略過⼀些程式 double getBonus (){ return salary * 3 ; } } class Tester extends Employee { // 略過⼀些程式 double getBonus (){ return salary * 1.5 ; } } class Artist extends Employee { // 略過⼀些程式 double getBonus (){ return salary * 2 ; } } class Main { public static void main( String [] args){ Programmer p = new Programmer (); Tester t = new Tester (); Artist a = new Artist (); p.salary = 40000 ; t.salary = 30000 ; a.salary = 35000 ; System.out.println( p.getBonus ()); System.out.println( t.getBonus ()); System.out.println( a.getBonus ()); } } 執⾏結果 120000 60000 80000 class Programmer extends Employee { // 略過⼀些程式 double getBonus (){ return salary * 3 ; } } class Tester extends Employee { // 略過⼀些程式 double getBonus (){ return salary * 1.5 ; } } class Artist extends Employee { // 略過⼀些程式 double getBonus (){ return salary * 2 ; } } 編譯時發⽣錯誤 ./Programmer.java:1: error: Programmer is not abstract and does not override abstract method getBonus() in Employee class Programmer extends Employee{ ^ ./Tester.java:1: error: Tester is not abstract and does not override abstract method getBonus() in Employee class Tester extends Employee{ ^ ./Artist.java:1: error: Artist is not abstract and does not override abstract method getBonus() in Employee class Artist extends Employee{ ^ 3 errors abstract class XEmployee extends Employee { // 略過⼀些程式 double getBonus () { return salary* 10 ; } } class Main { public static void main( String [] args){ XEmployee x = new XEmployee (); } } abstract class Employee extends Person{ String employeeID; int salary; void show(){ super .show(); System.out.println( " 員⼯編號是 " + employeeID); System.out.println( " 薪資是 " + salary); } abstract double getBonus () ; } 編譯時發⽣錯誤 Employee.java:1: error: Employee is not abstract and does not override abstract method getBonus() in Employee class Employee extends Person{ ^ 1 error J6_6_1 – Main.java 1. abstract 關鍵字加在加在 class 關鍵字的前⾯, 代表著此類別將會被定義為抽象化的。 J6_6_2 – Employee.java 1. 建立⼀個員⼯物件( Employee ),再次提醒,這只是⼀員⼯物件,並不是程 式設計師( Programmer ),測試⼈員( Tester )或是美⼯⼈員( Artist )。 2. e 變數中的是⼀個純員⼯物件,因此是無法轉型成程式設計師物件(⼜或 是測試⼈員物件、美⼯⼈員物件)的,因為向下轉型(即強迫轉型)的關 係,表⽰我們很明確的告訴編譯器這就是⼀個程式設計師物件,因此編譯成 功。但到實際執⾏的時候呢?您會由 JVM 得到⼀個異常物件,告訴您此員⼯ 物件無法轉型為程式設計師物件。若是如此,那為何要建立員⼯物件呢?員 ⼯物件⼀樣也有薪⽔屬性,難道是⽤來領薪⽔不作事的嗎?這合理嗎? J6_6_2 – Main.java 2. 雖然⼈員類別( Person )不是抽象類別,但⾝為 抽象類別的員⼯類別,還是可以繼承⾃⼈員類別。 3. 雖然是員⼯類別被抽象化了,但還是可以改寫繼承⾃ ⼈員類別( Person )的⾃我介紹⽅法( show() )。 4. 抽象化的員⼯類別,⼀如往常的可以作為型別來使⽤。在這段程式 中,程式設計師物件、測試⼈員物件或美⼯⼈員物件( Programmer 、 Tester 或 Artist )皆是可以轉型為員⼯型別的物件的。 J6_6_3 – Main.java 5. 嘗試著透過 new 來建立員⼯類別的物件,但因為員⼯類別是抽象化的,因此在編譯 的時候,編譯器會發⽣錯誤,告訴您不可建立抽象化的員⼯類別。很好,這樣就確保員 ⼯物件不會被建立,避免純員⼯物件因無法轉型為程式設計師物件、測試⼈員物件或美 ⼯⼈員物件,⽽無法⼯作,但卻有薪資屬性可設定薪資領薪的怪異問題存在。 J6_6_4 – Employee.java J6_6_4 – Programmer.java J6_6_4 – Tester.java J6_6_4 – Ar ? st.java J6_6_4 – Main.java 1. 這是繼承⾃員⼯類別的抽象化的員⼯類別( Employee )。 3. 雖然說不⽤加上⽅法本體(即⼤括號),但必須額外加上⼀個分號( ; )以表⽰結束。 2 . abstract 關鍵字也可以將⽅法變為抽象化的,與抽象類別的⽬的不同之處在於抽象⽅ 法是可以不必加上⽅法本體(即是⽅法後⾯的⼤括號 {} ),即表⽰可以不必事先決定⽅法要 如何執⾏,這樣就解決了需要為程式設計師、測試⼈員與美⼯⼈員預設獎⾦額度的問題。 4 . 每⼀個繼承⾃員⼯類別( Employee ) 的⼦類別,必須將繼承的抽象⽅法-獎⾦額 度⽅法改寫(⼜可稱為實作,因原類別為抽 象⽅法並無實體,則加上⽅法實體的動作即 稱為實作),並加上⽅法本體(即⼤括 號),如此才能完成獎⾦額度⽅法的定義。 5 . 分別建立程式設計師、測試⼈員、美⼯⼈員的物件( Programmer 、 Tester 與 Artist ),並分別設定薪資為 40000 、 30000 與 35000 。 6 . 最後呼叫取得獎⾦⽅法( getBonus() ), 仍能依照不同的⾓⾊取得應得的獎⾦額度。 J7_6_5 – Ar ? st.java J7_6_5 – Tester.java J7_6_5 – Programmer.java 1. 注意,這些類別皆繼承⾃員⼯類別( Employee ),⽽員⼯ 類別有個抽象⽅法-領取獎⾦⽅法( getBonus() )。 2 . 若非抽象化的⼦類別,繼承⾃抽象類別時,必須實作所有的抽象⽅法,若不實 作則會發⽣編譯錯誤,告訴您這是⼀個具象的類別(就是非抽象的意思),您必須 實作所有的抽象⽅法。這個原理很單純,只要是非描象化的類別,皆可以透過 new 來建立物件,但若是這個物件的類別繼承了未實作的抽象⽅法呢(就是沒有⽅法本 體)?那不就不知道如何執⾏這個⽅法了嗎?所以非抽象的類別⼀定要實作所有繼 承的抽象⽅法。在此繼承⾃員⼯的類別,皆需實作領取獎⾦這個抽象⽅法。 J6_6_6 – XEmployee.java J6_6_6 – Employee.java 1. 當⼦類別也被定義為抽象類別時,則這個⼦類別可以不必實 作繼承下來的抽象⽅法。在此的 XEmployee 即是⼀個抽象類 別,因此繼承員⼯類別後,並不需要實作領取獎⾦⽅法。 2. 因為抽象⽅法是不可以透過 new 建立實體物件的,因此也不⽤擔⼼沒有⽅ 法內容的抽象⽅法被拿來使⽤,進⽽造成抽象⽅法不知如何執⾏的情況。 J6_6_7 – Employee.java 1. 當⼀個類別中有抽象⽅法時,則這個類別也必須是⼀個抽象類別。若不 將類別也定義為抽象的,這時編譯器會發⽣錯誤,告訴您抽象⽅法是必須存 在於抽象類別中的。在此將員⼯類別前⽅的 abstract 取得,表⽰此類別不 是抽象類別,但其中卻擁有抽象化的領取獎⾦⽅法( getBonus() ),這是 不⾏的,編譯會失敗,抽象⽅法必須位於抽象類別中。 建立的員⼯物件,即不是程式設計師、測試⼈員或美⼯⼈ 員,那為什麼要建立員⼯物件呢? 第 2 步,確認員⼯物件不可被 new 出來 abstract ,抽象化獎⾦額度⽅法 注意,非抽象化的類別 必須改寫繼承的抽象⽅法 抽象化的類別,可以不實作繼承的抽象化⽅法 注意,抽象化⽅法必須放置於抽象類別中 1 1 1 2 3 1 2 3 1 2 3 1 2 3 1 1 留言
留言
張貼留言