面向對象接口多態

第3天 面向對象java

今日內容介紹
 接口
 多態
 筆記本案例
今日學習目標
 寫出定義接口的格式
 寫出實現接口的格式
 說出接口中成員的特色
 接口和抽象類的區別
 可以說出使用多態的前提條件
 理解多態的向上轉型
 理解多態的向下轉型
 可以完成筆記本電腦案例(方法參數爲接口)學習

第1章 接口優化

1.1 接口概念設計

類:具備相同屬性和功能的事物集合code

接口是功能的集合,一樣可看作是一種數據類型,是比抽象類更爲抽象的」類」。對象

接口只描述所應該具有的方法,並無具體實現,具體的實現由接口的實現類(至關於接口的子類)來完成。這樣將功能的定義與實現分離,優化了程序設計。
請記住:一切事物均有功能,即一切事物均有接口。繼承

1.2 接口的定義接口

與定義類的class不一樣,接口定義時須要使用interface關鍵字。
定義接口所在的仍爲.java文件,雖然聲明時使用的爲interface關鍵字的編譯後仍然會產生.class文件。這點可讓咱們將接口看作是一種只包含了功能聲明的特殊類。
定義格式:
public interface 接口名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
使用interface代替了原來的class,其餘步驟與定義類相同:
 接口中的方法均爲公共訪問的抽象方法
 接口中沒法定義普通的成員變量編譯

1.3 類實現接口程序設計

類與接口的關係爲實現關係,即類實現接口。實現的動做相似繼承,只是關鍵字不一樣,實現使用implements。
其餘類(實現類)實現接口後,就至關於聲明:」我應該具有這個接口中的功能」。實現類仍然須要重寫方法以實現具體的功能。
格式:
class 實現類 implements 接口 {

重寫接口中全部方法

}
在類實現接口後,該類就會將接口中的抽象方法繼承過來,此時該類須要重寫該抽象方法,完成具體的邏輯。
 接口中定義功能,當須要具備該功能時,可讓類實現該接口,只聲明瞭應該具有該方法,是功能的聲明。
 在具體實現類中重寫方法,實現功能,是方法的具體實現。
因而,經過以上兩個動做將功能的聲明與實現便分開了。(此時請從新思考:類是現實事物的描述,接口是功能的集合。)

1.4 接口中成員的特色

一、接口中能夠定義成員變量,可是變量必須有固定的修飾符修飾,public static final 因此接口中的變量也稱之爲常量,其值不能改變。後面咱們會講解static與final關鍵字
二、接口中能夠定義方法,方法也有固定的修飾符,public abstract
三、接口不能夠建立對象。
四、實現類必須覆蓋掉接口中全部的抽象方法後,實現類才能夠實例化。不然實現類是一個抽象類。

interface Demo { ///定義一個名稱爲Demo的接口。
    public static final int NUM = 3;// NUM的值不能改變
    public abstract void show1();
    public abstract void show2();
}

//定義子類去覆蓋接口中的方法。類與接口之間的關係是 實現。經過 關鍵字 implements
class DemoImpl implements Demo { //子類實現Demo接口。
    //重寫接口中的方法。
    public void show1(){}
    public void show2(){}
}

1.5 接口特色

 接口能夠繼承接口
如同類繼承類後便擁有了父類的成員,可使用父類的非私有成員。A接口繼承B接口後,A接口便擁有了A、B兩個接口中全部的抽象方法。
 Java支持一個類同時實現多個接口,或一個接口同時繼承多個接口。
 類能夠在繼承一個類的同時,實現多個接口。
 接口與父類的功能能夠重複,均表明要具有某種功能,並不衝突。

1.6 接口和抽象類的區別*

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

吼叫;
吃飯;

緝毒犬:
行爲:

吼叫;
吃飯;
緝毒;

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

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

    public void 緝毒() {
    }
    void 吃飯() {
    }
    void 吼叫() {
    }
}
class 緝毒豬 implements 緝毒{
    public void 緝毒() {
    }
}

三、經過上面的例子總結接口和抽象類的區別:
相同點:
 都位於繼承的頂端,用於被其餘類實現或繼承;
 都不能直接實例化對象;
 均可以包含抽象方法,其子類都必須覆寫這些抽象方法;
區別:
 抽象類爲部分方法提供實現,避免子類重複實現這些方法,提升代碼重用性;
 接口只能包含抽象方法;
 一個類只能繼承一個直接父類(多是抽象類),卻能夠實現多個接口;(接口彌補了Java的單繼承)

 抽象類爲繼承體系中的共性內容,接口爲繼承體系外的擴展功能

兩者的選用:
 優先選用接口,儘可能少用抽象類;
 須要定義子類的行爲,又要爲子類提供共性功能時才選用抽象類;

第2章 多態

2.1 多態概述

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

2.2 多態代碼體現

Java中多態的代碼體如今一個子類對象(實現類對象)既能夠給這個子類(實現類對象)引用變量賦值,又能夠給這個子類(實現類對象)的父類(接口)變量賦值。
如Student類能夠爲Person類的子類。那麼一個Student對象既能夠賦值給一個Student類型的引用,也能夠賦值給一個Person類型的引用。
最終多態體現爲父類引用變量能夠指向子類對象。
多態的前提是必須有子父類關係或者類實現接口關係,不然沒法完成多態。
在使用多態後的父類引用變量調用方法時,會調用子類重寫後的方法。

具體格式以下:
父類引用指向子類對象就是多態的定義格式。同一個父類的方法會被不一樣的子類重寫爲各自的具體實現。在調用方法時,調用的爲各個子類重寫後的方法。
父類類型 變量名 = new 子類類型();
變量名.方法名();
此時,雖然該變量指向的是子類對象,但表現爲一個父類的形態,能夠調用一切父類的方法,子類特有的方法將不能調用。

2.3 多態調用注意事項

 成員變量編譯看父類中是否存在,不存在編譯失敗
 成員變量運行父類中的變量
 成員方法編譯看父類中是否存在,不存在編譯失敗
 成員方法運行子類重寫的方法

2.4 多態的好處和弊端(貓狗的案例)**

當變量名指向不一樣的子類對象時,因爲每一個子類重寫父類方法的內容不一樣,因此會調用不一樣的方法。
如:
在Boss類中,有叫員工去工做的方法,當該方法的參數定義爲接口時,能夠傳入任意的子類對象。相比定義多個子類參數,定義多個方法,這樣大大提升了代碼複用性與擴展性。

class Boss{
    public void goToWork(Empolyee e){
        e.work();
    }
}

因此多態的存在乎義(優勢)爲:
配合繼承與方法重寫提升了代碼的複用性與擴展性,若是沒有方法重寫,則多態一樣沒有意義。

多態的弊端: 不能調用子類的特有方法

2.5 向上向下類型轉換

多態自己是子類類型向父類類型向上轉型的過程。
多態的轉型分爲向上轉型與向下轉型兩種:
 向上轉型:當有子類對象賦值給一個父類引用時,即是向上轉型,多態自己就是向上轉型的過程。
使用格式:
父類類型 變量名 = new 子類類型();
如:Animal p = new Cat();
 向下轉型:一個已經向上轉型的子類對象可使用強制類型轉換的格式,將父類引用轉爲子類引用,這個過程是向下轉型。若是是直接建立父類對象,是沒法向下轉型的!
使用格式:
子類類型 變量名 = (子類類型) 父類類型的變量;
如:Cat c = (Cat) a; //變量p 實際上指向Cat對象

 instanceof關鍵字
使用格式:
boolean b = 引用變量 instanceof 類;
if(a instanceof Dog){
Dog d = (Dog)a;
}

第3章 筆記本電腦案例

3.1 案例介紹

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

進行描述筆記本類,實現筆記本使用USB鼠標、USB鍵盤
 USB接口,包含開啓功能、關閉功能
 筆記本類,包含運行功能、關機功能、使用USB設備功能
 鼠標類,要符合USB接口
 鍵盤類,要符合USB接口

3.2 案例需求分析

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

3.3 實現代碼步驟

 定義鼠標、鍵盤,筆記本三者之間應該遵照的規則
interface USB {

void open();// 開啓功能
void close();// 關閉功能

}

 鼠標實現USB規則
class Mouse implements USB {

publicvoid open() {
    System.out.println("鼠標開啓");
}
publicvoid close() {
    System.out.println("鼠標關閉");
}

}

 鍵盤實現USB規則
class KeyBoard implements USB {

publicvoid open() {
    System.out.println("鍵盤開啓");
}
publicvoid close() {
    System.out.println("鍵盤關閉");
}

}

 定義筆記本

class NoteBook {
    // 筆記本開啓運行功能
    publicvoid run() {
        System.out.println("筆記本運行");
    }

    // 筆記本使用usb設備,這時當筆記本對象調用這個功能時,必須給其傳遞一個符合USB規則的USB設備
    publicvoid useUSB(USB usb) {
        // 判斷是否有USB設備
        if (usb != null) {
            usb.open();
            usb.close();
        }
    }

    publicvoid shutDown() {
        System.out.println("筆記本關閉");
    }
}

publicclass Test {
    publicstaticvoid 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();
    }
}
相關文章
相關標籤/搜索