20145216 《Java程式設計》第4周學習總結
教材學習內容總結
第六章 繼承與多型
6.1 何謂繼承
-
繼承基本上就是避免多個類間重複定義共同行為。
-
在Java中,繼承時使用extends關鍵字,private成員也會被繼承,只不過子類無法直接存取,必須通過父類提供的方法來存取(如果父類願意提供訪問方法的話)。如:
public class SwordsMan extends Role { public void fight() { System.out.println("揮劍攻擊"); } }
-
繼承範例:
public class RPG1 { public static void main(String[] args) { demoSwordsMan1(); demoMagician1(); } static void demoSwordsMan1() { SwordsMan1 swordsMan1 = new SwordsMan1(); swordsMan1.setName("Justin"); swordsMan1.setLevel(1); swordsMan1.setBlood(200); System.out.printf("劍士:(%s,%d,%d)%n",swordsMan1.getName(),swordsMan1.getLevel(),swordsMan1.getBlood()); } static void demoMagician1() { Magician1 magician1 = new Magician1(); magician1.setName("Monica"); magician1.setLevel(1); magician1.setBlood(100); System.out.printf("魔法師:(%s,%d,%d)%n",magician1.getName(),magician1.getLevel(),magician1.getBlood()); } }
-
繼承的好處:若你要將name、level、blood改為其他名稱,那就只要修改Role.java就可以了,只要是繼承Role的子類都無須修改。
-
在Java中,子類只能繼承一個父類,繼承有個重要的關係,就是子類與父類間會有is-a的關係,中文稱為“是一種”的關係。
-
檢查多型語法邏輯是否正確,方式是從=右邊往左讀;右邊是不是一種左邊呢(右邊型別是不是左邊型別的子類)?如果不是就會編譯失敗,如果加上扮演(Cast)語法,編譯程式就讓程式程式碼通過編譯,不過後果得自行負責,也就是扮演失敗,執行時會丟擲ClassCastException。
-
多型就是使用單一介面操作多種型別的物件。
-
在繼承父類之後,定義與父類中相同的方法部署,但執行內容不同,這稱為重新定義。如:
父類:
public class Role3
{
...
public void fight()
{
//子類要重新定義fight的實際行為
}
}
子類:
public class SwordsMan3 extends Role3
{
public void fight()
{
System.out.println("揮劍攻擊");
}
}
-
如果在子類中某個方法前標註@Override,表示要求編譯程式檢查,該方法是不是真的重新定義了父類中某個方法,如果不是的話,就會引發編譯錯誤。
-
如果某方法區塊中真的沒有任何程式中程式碼操作,可以使用abstract標示該方法為抽象方法,該方法不用撰寫{}區塊,直接“;”結束即可。
-
子類如果繼承抽象類,對於抽象方法有兩種做法: 一種做法是繼續標示該方法為abstract;另一種做法就是操作抽象方法。
6.2 繼承語法細節
- 被宣告為protected的成員,相同包中的類可以直接存取,不同包中的類可以在繼承後的子類直接存取。如:
父類:
public abstract class Role5
{
protected String name;
protected int level;
protected int blood;
...略
}
子類:
public class SwordsMan5 extends Role5
{
...
public String toString()
{
return String.format("劍士 (%s,%d,%d",this.name,this.level,this.blood);
}
}
-
Java中有public、protected與private三個許可權關鍵字,但實際上有四個許可權範圍:
-
在Java中,如果想取得父類中的方法定義,可以在呼叫方法前,加上super關鍵字。如:
public class SwordsMan6 extends Role6 { ... @Override public String toString() { return "劍士" + super.toString(); } }
-
重新定義方法要注意,對於父類中的方法許可權,只能擴大但不能縮小。
-
如果子類建構函式中沒有指定執行父類中哪個函式,預設會呼叫父類中無引數建構函式。
-
this()與super()只選擇一呼叫,而且一定要在建構函式第一行執行。
-
如果class前使用了final關鍵字定義,那麼表示這個類是最後一個了,不會再有子類,也就是不能被繼承。定義方法時,也可以限定該方法為final,這表示最後一次定義方法了,也就是子類不可以重新定義final方法。
-
在Java中,子類只能繼承一個父類,如果定義類時沒有使用extends關鍵字指定繼承任何類,那一定是繼承java.lang.Object。
第七章 介面與多型
7.1 何謂介面
-
對於“定義行為”,在Java中可以使用interface關鍵字定義。如:
public interface Swimmer1 { public abstract void swim(); }
-
介面可以用於定義行為但不定義操作。
-
類要操作介面,必須使用implements關鍵字。操作某介面時,對介面中定義的方法有兩種處理方式:一是操作介面中定義的方法;二是再度將該方法標示為abstract。如:(第二種方法)
public abstract class Fish1 implements Swimmer1 { protected String name; public Fish1(String name) { this.name = name; } public String getName() { return name; } @Override public abstract void swim(); }
-
以Java的語意來說,繼承會有“是一種”關係,操作介面則表示“擁有行為”,但不會有“是一種”的關係。
-
在Java中,類可以操作兩個以上的類,也就是擁有兩種以上的行為。如:
public class Seaplane3 implements Swimmer1,Flyer3 { private String name; public Seaplane3(String name) { this.name = name; } @Override { System.out.printf("海上飛機 %s 在飛%n",name); } @Override public void swim() { System.out.printf("海上飛機 %s 航行海綿%n",name); } }
-
在Java中,類可以同事繼承某個類,並操作某些介面。如:
public class FlyingFish3 extends Fish1 implements Flyer3 { public FlyingFish3(String name) { super(name); } @Override public void swim() { System.out.println("飛魚游泳"); } @Override public void fly() { System.out.println("飛魚會飛"); } }
-
在Java中,介面可以繼承自另一個介面,也就是繼承父介面行為,再在子介面中額外定義行為。如:
父類:
public class Boat4 implements Swimmer1
{
protected String name;
public Boat4(String name)
{
this.name = name;
}
@Override
public void swim()
{
System.out.printf("船在水面 %s 航行%n", name);
}
}
子類:
public class Submarine4 extends Boat4 implements Diver4
{
public Submarine4(String name)
{
super(name);
}
@Override
public void dive()
{
System.out.printf("潛水艇 %s 潛行%n",name);
}
}
7.2 介面語法細節
-
在Java中,可使用interface來定義抽象的行為與外觀,如介面中的方法可宣告為public abstract。
-
介面中的方法沒有操作時,一定得是公開且抽象。
-
在介面中列舉常數,一定要使用=指定值。並且介面列舉常數一定是public static final。
-
介面可以繼承別的介面,也可以同時繼承兩個以上的介面,同樣也是使用extends關鍵字,這代表了繼承父介面的行為。
-
如果有臨時繼承某個類或操作某個介面並建立例項的需求,而這類子類或介面操作類只使用一次,不需要為這些類定義名稱,這是可以使用匿名內部類來解決這個需求。匿名內部類的語法為:
new 父類()|介面(){ //類本體操作 };
-
enum實際上定義了類,而enum中列舉的常數,實際上是public static final,且為列舉型別例項,無法撰寫程式直接例項化列舉型別,因為建構函式許可權設定為private,只要類中才可以例項化。如:
import static java.lang.System.out; public class EnumGame { public static void main(String[] args) { play(EnumAction.RIGHT); play(EnumAction.UP); } public static void play(EnumAction action) { switch (action) { case STOP: out.println("播放停止動畫"); break; case RIGHT: out.println("播放向右動畫"); break; case LEFT: out.println("播放向左動畫"); break; case UP: out.println("播放向上動畫"); break; case DOWN: out.println("播放向下動畫"); break; } } }
教材學習中的問題和解決過程
問題:
在結合教材、視訊和老師部落格中的學習指導學習了第六、七章後,發現對於老師給出的思考題——介面與抽象類的區別還是不太清楚。
解決過程:
通過上網百度,我終於弄明白了介面與抽象類的區別,以下是我根據查詢的資料總結的二者區別:
-
語法層面上的區別
1、抽象類可以提供成員方法的實現細節,而介面中只能存在public abstract方法; 2、抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是public static final型別的; 3、一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。
-
設計層面上的區別
1、抽象類是對一種事物的抽象,即對類抽象,而介面是對行為的抽象;抽象類是對整個類整體進行抽象,包括屬 性、行為,但是介面卻是對類區域性(行為)進行抽象。 2、對於抽象類,如果需要新增新的方法,可以直接在抽象類中新增具體的實現,子類可以不進行變更;而對於接 口則不行,如果介面進行了變更,則所有實現這個介面的類都必須進行相應的改動。
程式碼除錯中的問題和解決過程
問題:
由於教材中的很多範例程式碼的類名都相同,於是我在類名後編上了號,結果自己敲完程式碼後出現如圖所示錯誤:
解決過程:
經過反覆檢視錯誤程式碼,我發現該程式碼中的宣告型別(Role)沒有與父類的類名(Role1)保持一致,於是我做了以下修改:
最後執行得到正確結果:
總結:
給類名編號後雖然解決了類名重複的問題,但是在敲程式碼時特別容易出錯,因為很多程式程式碼都是相關聯的,必須始終保持建立時的類名和引用時的名稱一致,所以在敲程式碼時一定要細心,並且要先弄懂每行程式碼的含義,這樣才能儘量避免程式碼中的錯誤。
本週程式碼託管截圖
其他(感悟、思考等,可選)
本週主要學習了繼承與介面的相關知識點,雖然內容較多,對我來說也有一定難度,但是經過對教材的反覆研讀與琢磨,還是可以慢慢理解和掌握的,當然我也有過因為理解不了程式碼的含義而煩躁的時候,也想過直接按照書上的程式碼敲,放棄理解不懂的內容,但是靜下心來,還是決定要好好學這門課,其實教材的講解很詳細,程式碼例項也都與我們所熟悉的內容相關,比如第六章是遊戲中的角色,第七章是開發一個海洋樂園遊戲,還有類圖以及其他的圖片解釋,這些都方便了我的理解,所以,儘管在學習Java的過程中有許多困難,但是隻要自己不放棄就能一一解決問題。
學習進度條
程式碼行數(新增/累積) | 部落格量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 4500行 | 30篇 | 350小時 | 能將java運用自如 |
第一週 | 150/150 | 2/2 | 15/15 | 學習了與java相關的基礎知識 |
第二週 | 200/350 | 1/3 | 20/35 |
學習了java的基本語法 |
第三週 | 450/800 | 1/4 | 25/60 |
學習了物件和封裝的相關知識 |
第四周 | 687/ 1487 | 1/5 | 30/90 |
學習了繼承與介面的相關知識 |