面向物件介面多型
第3天 面向物件
今日內容介紹
介面
多型
筆記本案例
今日學習目標
寫出定義介面的格式
寫出實現介面的格式
說出介面中成員的特點
介面和抽象類的區別
能夠說出使用多型的前提條件
理解多型的向上轉型
理解多型的向下轉型
能夠完成膝上型電腦案例(方法引數為介面)
第1章介面
1.1介面概念
類:具有相同屬性和功能的事物集合
介面是功能的集合,同樣可看做是一種資料型別,是比抽象類更為抽象的”類”。
介面只描述所應該具備的方法,並沒有具體實現,具體的實現由介面的實現類(相當於介面的子類)來完成。這樣將功能的定義與實現分離,優化了程式設計。
請記住:一切事物均有功能,即一切事物均有介面。
1.2介面的定義
與定義類的class不同,介面定義時需要使用interface關鍵字。
定義介面所在的仍為.java檔案,雖然宣告時使用的為interface關鍵字的編譯後仍然會產生.class檔案。這點可以讓我們將介面看做是一種只包含了功能宣告的特殊類。
定義格式:
public interface 介面名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
使用interface代替了原來的class,其他步驟與定義類相同:
介面中的方法均為公共訪問的抽象方法
介面中無法定義普通的成員變數
1.3類實現介面
類與介面的關係為實現關係,即類實現介面。實現的動作類似繼承,只是關鍵字不同,實現使用implements。
其他類(實現類)實現介面後,就相當於宣告:”我應該具備這個介面中的功能”。實現類仍然需要重寫方法以實現具體的功能。
格式:
class 實現類 implements 介面 {
重寫介面中所有方法
}
在類實現介面後,該類就會將介面中的抽象方法繼承過來,此時該類需要重寫該抽象方法,完成具體的邏輯。
介面中定義功能,當需要具有該功能時,可以讓類實現該介面,只聲明瞭應該具備該方法,是功能的宣告。
在具體實現類中重寫方法,實現功能,是方法的具體實現。
於是,通過以上兩個動作將功能的宣告與實現便分開了。(此時請重新思考:類是現實事物的描述,介面是功能的集合。)
1.4介面中成員的特點
1、介面中可以定義成員變數,但是變數必須有固定的修飾符修飾,public static final 所以介面中的變數也稱之為常量,其值不能改變。後面我們會講解static與final關鍵字
2、介面中可以定義方法,方法也有固定的修飾符,public abstract
3、介面不可以建立物件。
4、實現類必須覆蓋掉介面中所有的抽象方法後,實現類才可以例項化。否則實現類是一個抽象類。
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介面和抽象類的區別*
明白了介面思想和介面的用法後,介面和抽象類的區別是什麼呢?介面在生活體現也基本掌握,那在程式中介面是如何體現的呢?
通過例項進行分析和程式碼演示抽象類和介面的用法。
1、舉例:
犬:
行為:
吼叫; 吃飯;
緝毒犬:
行為:
吼叫; 吃飯; 緝毒;
2、思考:
由於犬分為很多種類,他們吼叫和吃飯的方式不一樣,在描述的時候不能具體化,也就是吼叫和吃飯的行為不能明確。當描述行為時,行為的具體動作不能明確,這時,可以將這個行為寫為抽象行為,那麼這個類也就是抽象類。
可是當緝毒犬有其他額外功能時,而這個功能並不在這個事物的體系中。這時可以讓緝毒犬具備犬科自身特點的同時也有其他額外功能,可以將這個額外功能定義介面中。
如下程式碼演示:
interface 緝毒{ public abstract void 緝毒(); } //定義犬科的這個提醒的共性功能 abstract class 犬科{ public abstract void 吃飯(); public abstract void 吼叫(); } // 緝毒犬屬於犬科一種,讓其繼承犬科,獲取的犬科的特性, //由於緝毒犬具有緝毒功能,那麼它只要實現緝毒介面即可,這樣即保證緝毒犬具備犬科的特性,也擁有了緝毒的功能 class 緝毒犬 extends 犬科 implements 緝毒{ public void 緝毒() { } void 吃飯() { } void 吼叫() { } } class 緝毒豬 implements 緝毒{ public void 緝毒() { } }
3、通過上面的例子總結介面和抽象類的區別:
相同點:
都位於繼承的頂端,用於被其他類實現或繼承;
都不能直接例項化物件;
都可以包含抽象方法,其子類都必須覆寫這些抽象方法;
區別:
抽象類為部分方法提供實現,避免子類重複實現這些方法,提高程式碼重用性;
介面只能包含抽象方法;
一個類只能繼承一個直接父類(可能是抽象類),卻可以實現多個介面;(介面彌補了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 子類型別();
如:Animalp = 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(); } }