一、接口 二、多態

01接口的概念

* A:接口的概念
    接口是功能的集合,一樣可看作是一種數據類型,是比抽象類更爲抽象的」類」。
    接口只描述所應該具有的方法,並無具體實現,具體的實現由接口的實現類(至關於接口的子類)來完成。這樣將功能的定義與實現分離,優化了程序設計。
    請記住:一切事物均有功能,即一切事物均有接口。

02接口的定義

* A: 接口的定義
        與定義類的class不一樣,接口定義時須要使用interface關鍵字。
        定義接口所在的仍爲.java文件,雖然聲明時使用的爲interface關鍵字的編譯後仍然會產生.class文件。這點可讓咱們將接口看作是一種只包含了功能聲明的特殊類。

                            
* B : 定義格式
        public interface 接口名 {
            抽象方法1;
            抽象方法2;
            抽象方法3;
        }
* C: 定義步驟
        使用interface代替了原來的class,其餘步驟與定義類相同:
        接口中的方法均爲公共訪問的抽象方法
        接口中沒法定義普通的成員變量

03接口的實現類

* A: 類與接口的關係
        類與接口的關係爲實現關係,即類實現接口。實現的動做相似繼承,只是關鍵字不一樣,實現使用implements。
        其餘類(實現類)實現接口後,就至關於聲明:」我應該具有這個接口中的功能」。實現類仍然須要重寫方法以實現具體的功能。
* B: 類實現接口的格式
        class 類 implements 接口 {
            重寫接口中方法
        } 
* C:注意事項
         在類實現接口後,該類就會將接口中的抽象方法繼承過來,此時該類須要重寫該抽象方法,完成具體的邏輯。
        接口中定義功能,當須要具備該功能時,可讓類實現該接口,只聲明瞭應該具有該方法,是功能的聲明。
        在具體實現類中重寫方法,實現功能,是方法的具體實現。

04接口中成員變量的特色

* A:成員變量特色
     * a 接口中能夠定義變量,可是變量必須有固定的修飾符修飾,public static final 因此接口中的變量也稱之爲常量,其值不能改變。後面咱們會講解static與final關鍵字
        

* B:案例
        interface Demo { ///定義一個名稱爲Demo的接口。
            public static final int NUM = 3;// NUM的值不能改變
        }

05接口中成員方法的特色

* A: 成員方法特色
    * a 接口中能夠定義方法,方法也有固定的修飾符,public abstract
    * b 子類必須覆蓋掉接口中全部的抽象方法後,子類才能夠實例化。不然子類是一個抽象類。

* B: 案例
        interface Demo { ///定義一個名稱爲Demo的接口。
            public abstract void show1();
            public abstract void show2();
        }
        
        //定義子類去覆蓋接口中的方法。類與接口之間的關係是 實現。經過 關鍵字 implements
        class DemoImpl implements Demo { //子類實現Demo接口。
            //重寫接口中的方法。
            public void show1(){}
            public void show2(){}
        }

06實現類仍是一個抽象類

A: 接口的實現類
   一個類若是實現類接口,有兩種操做方法:
   第一:實現類是非抽象類,就須要重寫接口中全部的抽象方法.
   第二:實現類也聲明爲抽象類,那麼實現類能夠不重寫接口中的抽象方法。

==============================第二節課開始====================================java

07類和接口的多實現

* A:接口的多實現
    瞭解了接口的特色後,那麼想一想爲何要定義接口,使用抽象類描述也沒有問題,接口到底有啥用呢?
    接口最重要的體現:解決多繼承的弊端。將多繼承這種機制在java中經過多實現完成了。
    
* B 多實現的優勢
    * 怎麼解決多繼承的弊端呢?
    * 弊端:多繼承時,當多個父類中有相同功能時,子類調用會產生不肯定性。
    * 其實核心緣由就是在於多繼承父類中功能有主體,而致使調用運行時,不肯定運行哪一個主體內容。
    * 爲何多實現能解決了呢?
    * 由於接口中的功能都沒有方法體,由子類來明確。

* C :案例演示
    interface Fu2{
        void show2();
    }
    class Zi implements Fu1,Fu2 {    // 多實現。同時實現多個接口。
        public void show1(){}
        public void show2(){}
    }

08類在繼承類的同時實現多接口

* A: 繼承的同時實現接口
    * 接口和類之間能夠經過實現產生關係,同時也學習了類與類之間能夠經過繼承產生關係。當一個類已經繼承了一個父類,它又須要擴展額外的功能,這時接口就派上用場了。
    * 子類經過繼承父類擴展功能,經過繼承擴展的功能都是子類應該具有的基礎功能。若是子類想要繼續擴展其餘類中的功能呢?這時經過實現接口來完成。
    * 接口的出現避免了單繼承的侷限性。父類中定義的事物的基本功能。接口中定義的事物的擴展功能。
    
* B: 代碼演示
    class Fu {
        public void show(){}
    }
    interface Inter {
        pulbic abstract void show1();
    }
    class Zi extends Fu implements Inter {
        public void show1() {
        }
    }

    接口的出現避免了單繼承的侷限性。父類中定義的事物的基本功能。接口中定義的事物的擴展功能。

09接口的多繼承

* A: 接口的多繼承
    * 學習類的時候,知道類與類之間能夠經過繼承產生關係,接口和類之間能夠經過實現產生關係,那麼接口與接口之間會有什麼關係。
    * 多個接口之間可使用extends進行繼承。
    
* B 代碼演示
     interface Fu1{
        void show();
    }
    interface Fu2{
        void show1();
    }
    interface Fu3{
        void show2();
    }
    interface Zi extends Fu1,Fu2,Fu3{
        void show3();
    }
    
    在開發中若是多個接口中存在相同方法,這時如有個類實現了這些接口,那麼就要實現接口中的方法,因爲接口中的方法是抽象方法,子類實現後也不會發生調用的不肯定性。

10接口思想

* A:接口的思想
    * 前面學習了接口的代碼體現,如今來學習接口的思想,接下里從生活中的例子進行說明。
    * 舉例:咱們都知道電腦上留有不少個插口,而這些插口能夠插入相應的設備,這些設備爲何能插在上面呢?
    * 主要緣由是這些設備在生產的時候符合了這個插口的使用規則,不然將沒法插入接口中,更沒法使用。發現這個插口的出現讓咱們使用更多的設備。

* B: 接口的好處    
    * 總結:接口在開發中的它好處
    * 一、接口的出現擴展了功能。
    * 二、接口其實就是暴漏出來的規則。
    * 三、接口的出現下降了耦合性,即設備與設備之間實現瞭解耦。
    
    * 接口的出現方便後期使用和維護,一方是在使用接口(如電腦),一方在實現接口(插在插口上的設備)。例如:筆記本使用這個規則(接口),電腦外圍設備實現這個規則(接口)。

11接口和抽象類的區別

* A: 明白了接口思想和接口的用法後,接口和抽象類的區別是什麼呢?接口在生活體現也基本掌握,那在程序中接口是如何體現的呢?
    經過實例進行分析和代碼演示抽象類和接口的用法。
* B: 舉例:
    *    犬:
            行爲:
            吼叫;
            吃飯;
    * 緝毒犬:
            行爲:
            吼叫;
            吃飯;
            緝毒;

* C:思考:
    * 因爲犬分爲不少種類,他們吼叫和吃飯的方式不同,在描述的時候不能具體化,也就是吼叫和吃飯的行爲不能明確。
    * 當描述行爲時,行爲的具體動做不能明確,這時,能夠將這個行爲寫爲抽象行爲,那麼這個類也就是抽象類。
    * 但是當緝毒犬有其餘額外功能時,而這個功能並不在這個事物的體系中。這時可讓緝毒犬具有犬科自身特色的同時也有其餘額外功能,能夠將這個額外功能定義接口中。

* D: 代碼演示
    interface 緝毒{
        public abstract void 緝毒();
    }
    //定義犬科的這個提醒的共性功能
    abstract class 犬科{
    public abstract void 吃飯();
    public abstract void 吼叫();
    }
    // 緝毒犬屬於犬科一種,讓其繼承犬科,獲取的犬科的特性,
    //因爲緝毒犬具備緝毒功能,那麼它只要實現緝毒接口便可,這樣即保證緝毒犬具有犬科的特性,也擁有了緝毒的功能
    class 緝毒犬 extends 犬科 implements 緝毒{
    
        public void 緝毒() {
        }
        void 吃飯() {
        }
        void 吼叫() {
        }
    }
    class 緝毒豬 implements 緝毒{
        public void 緝毒() {
        }
    }

* E: 接口和抽象類區別總結
     相同點:
        都位於繼承的頂端,用於被其餘類實現或繼承;
        都不能直接實例化對象;
        都包含抽象方法,其子類都必須覆寫這些抽象方法;
    區別:
        抽象類爲部分方法提供實現,避免子類重複實現這些方法,提升代碼重用性;接口只能包含抽象方法;
        一個類只能繼承一個直接父類(多是抽象類),卻能夠實現多個接口;(接口彌補了Java的單繼承)
        抽象類是這個事物中應該具有的你內容, 繼承體系是一種 is..a關係
        接口是這個事物中的額外內容,繼承體系是一種 like..a關係
    
    兩者的選用:
        優先選用接口,儘可能少用抽象類;
        須要定義子類的行爲,又要爲子類提供共性功能時才選用抽象類;

==============================第三節課開始====================================學習

12多態概述

* A: 多態概述
    多態是繼封裝、繼承以後,面向對象的第三大特性。
    現實事物常常會體現出多種形態,如學生,學生是人的一種,則一個具體的同窗張三既是學生也是人,即出現兩種形態。    
    Java做爲面向對象的語言,一樣能夠描述一個事物的多種形態。如Student類繼承了Person類,一個Student的對象便既是Student,又是Person。
    Java中多態的代碼體如今一個子類對象(實現類對象)既能夠給這個子類(實現類對象)引用變量賦值,又能夠給這個子類(實現類對象)的父類(接口)變量賦值。
    如Student類能夠爲Person類的子類。那麼一個Student對象既能夠賦值給一個Student類型的引用,也能夠賦值給一個Person類型的引用。
    最終多態體現爲父類引用變量能夠指向子類對象。
    多態的前提是必須有子父類關係或者類實現接口關係,不然沒法完成多態。
    在使用多態後的父類引用變量調用方法時,會調用子類重寫後的方法。

13多態調用的三種格式

* A:多態的定義格式:
    * 就是父類的引用變量指向子類對象
         父類類型  變量名 = new 子類類型();
         變量名.方法名();
    
* B: 普通類多態定義的格式
        父類 變量名 = new 子類();
        舉例:    
            class Fu {}
            class Zi extends Fu {}
            //類的多態使用
            Fu f = new Zi();
* C: 抽象類多態定義格式            
        抽象類 變量名 = new 抽象類子類();
        舉例:    
        abstract class Fu {
                 public abstract void method();
                 }
        class Zi extends Fu {
        public void method(){
                      System.out.println(「重寫父類抽象方法」);
        }
        }
        //類的多態使用
        Fu fu= new Zi();
* D: 接口多態定義的格式
        接口 變量名 = new 接口實現類();
        如: interface Fu {
                     public abstract void method();
        }
        class Zi implements Fu {
                     public void method(){
                      System.out.println(「重寫接口抽象方法」);
        }
        }
        //接口的多態使用
        Fu fu = new Zi();
* E: 注意事項
        同一個父類的方法會被不一樣的子類重寫。在調用方法時,調用的爲各個子類重寫後的方法。
        如 Person p1 = new Student();
           Person p2 = new Teacher();
           p1.work(); //p1會調用Student類中重寫的work方法
           p2.work(); //p2會調用Teacher類中重寫的work方法
        當變量名指向不一樣的子類對象時,因爲每一個子類重寫父類方法的內容不一樣,因此會調用不一樣的方法。

14多態成員方法的特色

* A: 掌握了多態的基本使用後,那麼多態出現後類的成員有啥變化呢?前面學習繼承時,咱們知道子父類之間成員變量有了本身的特定變化,
    * 那麼當多態出現後,成員變量在使用上有沒有變化呢?
    * 多態出現後會致使子父類中的成員變量有微弱的變化
* B: 代碼演示
    class Fu {
        int num = 4;
    }
    class Zi extends Fu {
        int num = 5;
    }
    class Demo {
        public static void main(String[] args)     {
            Fu f = new Zi();
            System.out.println(f.num);
            Zi z = new Zi();
            System.out.println(z.num);
        }
    }

* C: 多態成員變量
    當子父類中出現同名的成員變量時,多態調用該變量時:
    編譯時期:參考的是引用型變量所屬的類中是否有被調用的成員變量。沒有,編譯失敗。
    運行時期:也是調用引用型變量所屬的類中的成員變量。
    簡單記:編譯和運行都參考等號的左邊。編譯運行看左邊。

* D: 多態出現後會致使子父類中的成員方法有微弱的變化。看以下代碼
    class Fu {
        int num = 4;
        void show()    {
            System.out.println("Fu show num");
        }
    }
    class Zi extends Fu {
        int num = 5;
        void show()    {
            System.out.println("Zi show num");
        }
    }
    class Demo {
        public static void main(String[] args)     {
            Fu f = new Zi();
            f.show();
        }
    }

* E: 多態成員方法
    編譯時期:參考引用變量所屬的類,若是沒有類中沒有調用的方法,編譯失敗。
    運行時期:參考引用變量所指的對象所屬的類,並運行對象所屬類中的成員方法。
    簡而言之:編譯看左邊,運行看右邊。

15instanceof關鍵字

* A: 做用
     能夠經過instanceof關鍵字來判斷某個對象是否屬於某種數據類型。如學生的對象屬於學生類,學生的對象也屬於人類

* 格式:
    boolean  b  = 對象  instanceof  數據類型;

* 舉例:
    Person p1 = new Student(); // 前提條件,學生類已經繼承了人類
    boolean flag = p1 instanceof Student; //flag結果爲true
    boolean flag2 = p2 instanceof Teacher; //flag結果爲false

16多態-向上轉型

* A: 多態的轉型分爲向上轉型與向下轉型兩種:
    
* B: 向上轉型:當有子類對象賦值給一個父類引用時,即是向上轉型,多態自己就是向上轉型的過程。
    使用格式:
    父類類型  變量名 = new 子類類型();
    如:Person p = new Student();

==============================第四節課開始====================================優化

17多態-向下轉型

* A: 向下轉型:一個已經向上轉型的子類對象可使用強制類型轉換的格式,將父類引用轉爲子類引用,這個過程是向下轉型。若是是直接建立父類對象,是沒法向下轉型的!
    使用格式:
    子類類型 變量名 = (子類類型) 父類類型的變量;
    如:Student stu = (Student) p;  //變量p 實際上指向Student對象

18多態的好處和弊端

* A: 多態的好處和弊端
    * 當父類的引用指向子類對象時,就發生了向上轉型,即把子類類型對象轉成了父類類型。
      向上轉型的好處是隱藏了子類類型,提升了代碼的擴展性。
    * 但向上轉型也有弊端,只能使用父類共性的內容,而沒法使用子類特有功能,功能有限制。
    
* B: 看以下代碼
    //描述動物類,並抽取共性eat方法
    abstract class Animal {
        abstract void eat();
    }
     
    // 描述狗類,繼承動物類,重寫eat方法,增長lookHome方法
    class Dog extends Animal {
        void eat() {
            System.out.println("啃骨頭");
        }
    
        void lookHome() {
            System.out.println("看家");
        }
    }
    
    // 描述貓類,繼承動物類,重寫eat方法,增長catchMouse方法
    class Cat extends Animal {
        void eat() {
            System.out.println("吃魚");
        }
    
        void catchMouse() {
            System.out.println("抓老鼠");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Animal a = new Dog(); //多態形式,建立一個狗對象
            a.eat(); // 調用對象中的方法,會執行狗類中的eat方法
            // a.lookHome();//使用Dog類特有的方法,須要向下轉型,不能直接使用
            
            // 爲了使用狗類的lookHome方法,須要向下轉型
    // 向下轉型過程當中,可能會發生類型轉換的錯誤,即ClassCastException異常
            // 那麼,在轉以前須要作健壯性判斷 
            if( !a instanceof Dog){ // 判斷當前對象是不是Dog類型
                     System.out.println("類型不匹配,不能轉換"); 
                     return; 
            } 
            Dog d = (Dog) a; //向下轉型
            d.lookHome();//調用狗類的lookHome方法
        }
    }
* C 多態總結:
    何時使用向上轉型:
        當不須要面對子類類型時,經過提升擴展性,或者使用父類的功能就能完成相應的操做,這時就可使用向上轉型。
        如:Animal a = new Dog();
            a.eat();
    何時使用向下轉型
        當要使用子類特有功能時,就須要使用向下轉型。
            如:Dog d = (Dog) a; //向下轉型
                d.lookHome();//調用狗類的lookHome方法
            向下轉型的好處:可使用子類特有功能。
            弊端是:須要面對具體的子類對象;在向下轉型時容易發生ClassCastException類型轉換異常。在轉換以前必須作類型判斷。
        如:if( !a instanceof Dog){…}

19多態舉例

* A: 畢老師和畢姥爺的故事
 * 案例:
  /*
    描述畢老師和畢姥爺,
    畢老師擁有講課和看電影功能
    畢姥爺擁有講課和釣魚功能
  */
    class 畢姥爺 {
        void 講課() {
            System.out.println("政治");
        }
    
        void 釣魚() {
            System.out.println("釣魚");
        }
    }
    
    // 畢老師繼承了畢姥爺,就有擁有了畢姥爺的講課和釣魚的功能,
    // 但畢老師和畢姥爺的講課內容不同,所以畢老師要覆蓋畢姥爺的講課功能
    class 畢老師 extends 畢姥爺 {
        void 講課() {
            System.out.println("Java");
        }
    
        void 看電影() {
            System.out.println("看電影");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            // 多態形式
            畢姥爺 a = new 畢老師(); // 向上轉型
            a.講課(); // 這裏表象是畢姥爺,其實真正講課的仍然是畢老師,所以調用的也是畢老師的講課功能
            a.釣魚(); // 這裏表象是畢姥爺,但對象實際上是畢老師,而畢老師繼承了畢姥爺,即畢老師也具備釣魚功能
    
            // 當要調用畢老師特有的看電影功能時,就必須進行類型轉換
            畢老師 b = (畢老師) a; // 向下轉型
            b.看電影();
        }

20筆記本電腦案例

* A:案例介紹
     * 定義USB接口(具有開啓功能、關閉功能),筆記本要使用USB設備,即筆記本在生產時須要預留能夠插入USB設備的USB接口,即就是筆記本具有使用USB設備的功能,
     * 但具體是什麼USB設備,筆記本並不關心,只要符合USB規格的設備均可以。鼠標和鍵盤要想能在電腦上使用,那麼鼠標和鍵盤也必須遵照USB規範,否則鼠標和鍵盤的生產出來沒法使用
    * 進行描述筆記本類,實現筆記本使用USB鼠標、USB鍵盤
        USB接口,包含開啓功能、關閉功能
        筆記本類,包含運行功能、關機功能、使用USB設備功能
        鼠標類,要符合USB接口
        鍵盤類,要符合USB接口

* B: 案例分析
    * 階段一:
        使用筆記本,筆記本有運行功能,須要筆記本對象來運行這個功能
    * 階段二:
        想使用一個鼠標,又有一個功能使用鼠標,並多了一個鼠標對象。
    * 階段三:
        還想使用一個鍵盤 ,又要多一個功能和一個對象
    * 問題:每多一個功能就須要在筆記本對象中定義一個方法,不爽,程序擴展性極差。
        下降鼠標、鍵盤等外圍設備和筆記本電腦的耦合性。

21筆記本電腦案例代碼實現

* A: 代碼實現
    定義鼠標、鍵盤,筆記本三者之間應該遵照的規則
    interface USB {
        void open();// 開啓功能
    
        void close();// 關閉功能
    }
    
        鼠標實現USB規則
    class Mouse implements USB {
        public void open() {
            System.out.println("鼠標開啓");
        }
    
        public void close() {
            System.out.println("鼠標關閉");
        }
    }
    
        鍵盤實現USB規則
    class KeyBoard implements USB {
        public void open() {
            System.out.println("鍵盤開啓");
        }
    
        public void close() {
            System.out.println("鍵盤關閉");
        }
    }
    
        定義筆記本
    class NoteBook {
        // 筆記本開啓運行功能
        public void run() {
            System.out.println("筆記本運行");
        }
    
        // 筆記本使用usb設備,這時當筆記本對象調用這個功能時,必須給其傳遞一個符合USB規則的USB設備
        public void useUSB(USB usb) {
            // 判斷是否有USB設備
            if (usb != null) {
                usb.open();
                usb.close();
            }
        }
    
        public void shutDown() {
            System.out.println("筆記本關閉");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            // 建立筆記本實體對象
            NoteBook nb = new NoteBook();
            // 筆記本開啓
            nb.run();
    
            // 建立鼠標實體對象
            Mouse m = new Mouse();
            // 筆記本使用鼠標
            nb.useUSB(m);
    
            // 建立鍵盤實體對象
            KeyBoard kb = new KeyBoard();
            // 筆記本使用鍵盤
            nb.useUSB(kb);
    
            // 筆記本關閉
            nb.shutDown();
        }
    }

22總結

* 把今天的知識點總結一遍。
相關文章
相關標籤/搜索