第8章•繼承繼承繼承繼承、、、、多型多型多型多型–繼承–多型擴充(extends)父類別•使用extends作為其擴充父類別的關鍵字publicclassBird{privateStringname;publicBird(){}publicBird(Stringname){this.name=name;}publicvoidwalk(){System.out.println(走路);}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}}擴充(extends)父類別publicclassChickenextendsBird{//擴充Bird類別privateStringcrest;//新增私有成員,雞冠描述publicChicken(){super();}//定義建構方法publicChicken(Stringname,Stringcrest){super(name);this.crest=crest;}//新增方法publicvoidsetCrest(Stringcrest){this.crest=crest;}publicStringgetCrest(){returncrest;}publicvoidwu(){System.out.println(咕咕叫…);}}擴充(extends)父類別Chickenchicken1=newChicken(小克,紅色小雞冠);Chickenchicken2=newChicken();System.out.printf(小雞1-名稱%s,雞冠是%s。\n,chicken1.getName(),chicken1.getCrest());chicken1.wu();System.out.printf(小雞2-名稱%s,雞冠是%s。\n,chicken2.getName(),chicken2.getCrest());chicken2.wu();被保護的(protected)成員•保護意思表示存取該成員是有條件限制的•繼承的類別就可以直接使用這些成員,但這些成員仍然受到保護•不同套件(package)的物件不可直接呼叫使用protected成員被保護的(protected)成員publicclassRectangle{//受保護的memberprotectedintx;protectedinty;protectedintwidth;protectedintheight;…}publicclassCubicextendsRectangle{…publicintgetVolumn(){//可以直接使用父類別中的可以直接使用父類別中的可以直接使用父類別中的可以直接使用父類別中的width、、、、height成員成員成員成員returnlength*width*height;}}重新定義(Override)方法•如果父類別中的定義並不符合您的需求,可以在擴充類別的同時重新定義•可以重新定義方法的實作內容、成員的存取權限,或是成員的返回值型態重新定義(Override)方法publicclassSimpleArray{protectedint[]array;publicSimpleArray(inti){array=newint[i];}publicvoidsetElement(inti,intdata){array[i]=data;}....}publicclassSafeArrayextendsSimpleArray{…//重新定義重新定義重新定義重新定義setElement()publicvoidsetElement(inti,intdata){if(iarray.length)super.setElement(i,data);}....}重新定義(Override)方法SimpleArraysimpleArray=newSafeArray();simpleArray.setElement();•實際運作的物件是SafeArray的實例,所以被呼叫執行的會是SafeArray中重新定義過的setElement()方法重新定義(Override)方法•在衍生類別中想要呼叫基底類別的建構方法,可以使用super()方法•要在衍生類別中呼叫基底類別方法,則可以如使用super.methodName()•條件限制–父類別中的方法或建構方法不能是private,也就是不能是私用成員重新定義(Override)方法•您可以增大父類別中的方法權限,但不可以縮小父類別的方法權限–若原來成員是public的話,您不可以在父類別中重新定義它為private或protectedpublicclassSafeArrayextendsSimpleArray{//不可以縮小父類別中同名方法的權限privatevoidsetElement(inti,intdata){....}}setElement(int,int)inSafeArraycannotoverridesetElement(int,int)inSimpleArray;attemptingtoassignweakeraccessprivileges;waspublicprivatevoidsetElement(inti,intdata){^1error重新定義(Override)方法•從J2SE5.0開始在重新定義方法時,您可以重新定義返回值的型態publicclassBird{protectedStringname;publicBird(Stringname){this.name=name;}publicBirdgetCopied{returnnewBird(name);}}重新定義(Override)方法publicclassChickenextendsBird{protectedStringcrest;publicChicken(Stringname,Stringcrest){super(name);this.crest=crest;}//重新定義返回值型態為ChickenpublicChickengetCopied(){returnnewChicken(name,crest);}}•重新定義的返回值型態必須是父類別中同一方法返回型態的子類別•無法重新定義static方法Object類別•Object是Java程式中所有類別的父類別•每個類別都直接或間接繼承自Object類別publicclassFoo{//實作}publicclassFooextendsObject{//實作}toString()、equals()、hashCode()•toString()方法是對物件的文字描述•Object的toString()預設會傳回類別名稱及16進位制的編碼•預設的equals()本身是比較物件的記憶體位址是否相同getClass().getName()+'@'+Integer.toHexString(hashCode())toString()、equals()、hashCode()•可以重新定義equals()方法,以定義您自己的物件在什麼條件下可視為相等的物件•在重新定義equals()方法時,建議同時重新定義hashCode()方法toString()、equals()、hashCode()publicbooleanequals(Objectother){if(this==other)returntrue;if(!(otherinstanceofCat))returnfalse;finalCatcat=(Cat)other;if(!getName().equals(cat.getName()))returnfalse;if(!getBirthday().equals(cat.getBirthday()))returnfalse;returntrue;}publicinthashCode(){intresult=getName().hashCode();result=29*result+getBirthday().hashCode();returnresult;}clone()方法•如何複製物件本身•最基本的作法:實作java.lang.Cloneable介面(Interface)publicclassPointimplementsCloneable{//要實作Cloneable…publicObjectclone()throwsCloneNotSupportedException{//呼叫父類別的呼叫父類別的呼叫父類別的呼叫父類別的clone()來進行複製來進行複製來進行複製來進行複製returnsuper.clone();}}clone()方法publicclassTableimplementsCloneable{//要實作CloneableprivatePointcenter;//…publicObjectclone()throwsCloneNotSupportedException{//呼叫父類的呼叫父類的呼叫父類的呼叫父類的clone()來複製來複製來複製來複製Tabletable=(Table)super.clone();if(this.center!=null){//複製複製複製複製Point類型的資料成員類型的資料成員類型的資料成員類型的資料成員table.center=(Point)center.clone();}returntable;}}clone()方法Tabletable=newTable();table.setCenter(newPoint(2,3));PointoriginalCenter=table.getCenter();TableclonedTable=(Table)table.clone();PointclonedCenter=clonedTable.getCenter();System.out.printf(原來的Table中心:(%d,%d)\n,originalCenter.getX(),originalCenter.getY());System.out.printf(複製的Table中心:(%d,%d)\n,clonedCenter.getX(),clonedCenter.getY());clonedCenter.setX(10);clonedCenter.setY(10);//改變複製品的內容,對原來的物件不會有影響System.out.printf(原來的Table中心:(%d,%d)\n,originalCenter.getX(),originalCenter.getY());System.out.printf(複製的Table中心:(%d,%d)\n,clonedCenter.getX(),clonedCenter.getY());final關鍵字•“final”關鍵字使用在變數宣告時,表示該變數設定之後,就不可以再改變該變數的值•如果在定義方法成員時使用final,表示該方法成員在無法被子類別重新定義finaldoublePI=3.14159;publicclassBall{privatedoubleradius;publicfinaldoublegetRadius(){returnradius;}//....}final關鍵字•如果您在宣告類別時加上final關鍵字,則表示要終止被擴充publicfinalclassBall{//....}多型導論•如果使用不正確類別型態轉換物件操作介面,會發生java.lang.ClassCastException多型導論•定義了兩個execute()方法來分別操作Class1與Class2的實例•execute()分別依賴了Class1與Class2兩個類別publicvoidexecute(Class1c1){c1.doSomething()