20145216史婧瑤《Java 程式設計》第4周學習總結

20145216史婧瑤發表於2016-03-27

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 

學習了繼承與介面的相關知識 

參考資料

相關文章