面向對象程序設計面向對象程序設計核心內容及案例分析課件_第1頁
面向對象程序設計面向對象程序設計核心內容及案例分析課件_第2頁
面向對象程序設計面向對象程序設計核心內容及案例分析課件_第3頁
面向對象程序設計面向對象程序設計核心內容及案例分析課件_第4頁
面向對象程序設計面向對象程序設計核心內容及案例分析課件_第5頁
已閱讀5頁,還剩109頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

面向對象核心內容回顧及案例分析面向對象核心內容回顧及案例分析Ⅰ內容回顧Ⅰ內容回顧內容回顧列表1.繼承及繼承實例2.方法重寫(Overwrite)3.super關鍵字4.方法重載(Overload)5.final修飾符6.abstract修飾符7.抽象類8.接口9.接口和抽象類對比10.接口和抽象類使用場合實例內容回顧列表1.繼承及繼承實例1、繼承

剛開始講繼承的時候,我們就已經初始了繼承的概念:子類自動共享父類數據結構和方法的機制,這是類之間的一種關系。繼承也是提高代碼復用的有力手段,當多個類之間存在相同的屬性和方法時,就可以考慮繼承,從這些類中抽象出父類——在父類中定義這些相同的屬性和方法,子類無需再定義這些相同的屬性和方法,只需要通過extends語句來聲明繼承關系即可:繼承具有單根性:即一個類只能繼承最多一個類。不能出現:publicclassSonextends

Base,Base2{……}但是Base類可以繼承其他類。publicclassSonextendsBase{……}son:代表子類,又叫做超類。Base:代表父類,又叫做基類。1、繼承剛開始講繼承的時候,我們就已經初始了繼承的概念:繼繼承案例分析:門

所有門都擁有開(open)和關(close)這樣的動作,不管是普通的門還是安全門,所以我們這里定義一個公用的父類Door類,并且默認的認為所有的門的名字都叫門。public

classDoor{publicStringdoorName="門";//門的名字public

voidopen(){//開門方法System.out.println("門開了!");}public

voidclose(){//關門方法System.out.println("門關了");}}創建父類Door繼承案例分析:門所有門都擁有開(open)和關(close創建子類——CommonDoor和SecurityDoor

public

classCommDoorextendsDoor{}普通門CommDoor:public

classSecurityDoorextendsDoor{}安全門:創建子類——CommonDoor和SecurityDoor繼承測試

可以發現,在CommDoor和SecurityDoor中我們一行代碼都沒有寫,只是繼承了Door類,就可以直接使用open和close方法了。這正是繼承的特點——子類可以共享父類的數據和方法。public

static

voidmain(String[]args){CommDoorcd=newCommDoor();System.out.println(cd.doorName);cd.open();cd.close();SecurityDoorsd=newSecurityDoor();System.out.println(sd.doorName);sd.open();sd.close();}結果:如果說類的數量很多,那么這種優勢就更加顯而易見了。但是繼承的弱點是:打破了封裝,當父類一旦改變,子類也就可能發生變化,類的耦合度過高,不符合我們高內聚低耦合的設計原則。繼承測試可以發現,在CommDoor和SecurityDo2、方法重寫(Overwrite)

方法重寫(Overwrite)又叫方法覆蓋(Override),是有繼承關系的類之間的一種多態特性。如果,對于一般門,當調用open方的時候直接輸出“門開了”就好了,可是對于安全門我們可能在開門之前需要做一個身份驗證,以確定是否真的要開門。那么我們就需要在子類里面重寫父類的open方法。public

voidopen(){System.out.println("/*--安全門,模擬執行了安全驗證--*/");System.out.println("門開了!");}這種在子類中重新定義父類已有方法的行為就是重寫,重寫是多態的一種體現形式。2、方法重寫(Overwrite)方法重寫(Overwri3、super關鍵字

一般在以下情況我們會用到super關鍵字:1.在子類構造方法中,通過super調用父類構造方法2.在子類中訪問父類被覆蓋重寫的方法和屬性現在給Door添加構造方法,如下:publicDoor(StringdoorName){this.doorName=doorName;}在SecurityDoor中可以如下定義:publicSecurityDoor(StringdoorName,Stringbrand){super(doorName);this.brand=brand;}這里的super代表調用父類的構造方法。說明,SecurityDoor有一個自己的brand屬性。3、super關鍵字一般在以下情況我們會用到super關鍵3、super關鍵字

如果在子類中重寫了父類屬性,如在Security中重新定義了doorName屬性:privateStringdoorName="安全門";要想再訪問到父類的屬性,則可以使用:super.doorName;測試:System.out.println(this.doorName+""+super.doorName);結果:3、super關鍵字如果在子類中重寫了父類屬性,如在Sec4、方法重載(Overload)

方法重載(Overload),是類的同一功能(方法)有多種實現方式。其實重載在學習Math數學類的時候已經有所接觸了,如下:這里有四個都叫max的方法,但是他們的參數列表不同,這樣就可以實現,當我們不論輸入任何兩個數字型(double,int,float,long)的參數的時候,都能返回最大值。不需要定義doubleMax,floatMax,intMax,longMax這樣的方法。4、方法重載(Overload)方法重載(Overload

假設,我們的安全門現在有多種開門方式,可以使用鑰匙開門,使用6位密碼開門,輸入房號和訪客姓名請求開門三種方式。那么我們可以做如下定義:public

void

open(Stringkey){System.out.println("/*--用鑰匙開安全門,模擬驗證鑰匙是否正確--*/");System.out.println("門開了!");}public

void

open(int

pwd){System.out.println("/*--用6位密碼開門,模擬驗證密碼是否正確--*/");System.out.println("門開了!");}public

void

open(int

doorNo,StringvisitName){System.out.println("/*--"+visitName+"請求"+doorNo+"開門,模擬確定是否開門--*/");System.out.println("門開了!");}不允許僅僅返回值不同的重載。如:publicvoidopen(Stringkey){……}和publicStringopen(Stringkey){……}是不能通過編譯的。重載的特點:方法名都相同,參數列表不同。假設,我們的安全門現在有多種開門方式,可以使用鑰匙開門,使5、final修飾符

final修飾符可以修飾類,變量,方法。被final修飾的變量叫做常量,值不能被修改,如finalintPI=3.14;被final修飾的類不能被繼承。被final修飾的方法不能被重寫。5、final修飾符final修飾符可以修飾類,變量,方法6、abstract修飾符

abstract修飾符可以修飾類,方法。被abstract修飾的類叫做抽象類,抽象類不能被實例化。被abstract修飾的方法叫做抽象方法,抽象方法沒有方法體,不提供具體實現。public

abstract

classDoor{public

abstract

voidopen();}所謂不能實例,就是指不能:Doordoor=newDoor();所謂無方法體,不實現就是指:open方法沒有具體的指定實現。那么定義這樣的類和方法有什么用呢?我們最終當然要為這樣的類和方法提供一個實現,這個實現就是繼承他的類,他的子類可以為抽象方法提供具體的實現。抽象類通常代表一個抽象概念,可以用一句話來概括抽象類的用途:抽象類是用來繼承的。反過來可以說具體類不是用來繼承的,只要有可能,我們不要從具體類繼承——之前我們的做法雖然實現了功能,但是沒有達到思想上的真正意義。6、abstract修飾符abstract修飾符可以修飾類

使用abstract有以下幾個需要遵循的原則:抽象類中可以沒有抽象方法,但包含抽象方法的類就必須是抽象類。抽象方法不能是靜態的。抽象類及抽象方法不能被final修飾。抽象類不象具體類那樣描述一類具體事物,它是提取多種具有相似性的具體事物的共同特征而產生的。而不是一個具體描述對象的類。同時抽象類和抽象方法其實是面向契約的一種體現,抽象類就相當于一個制定者。對于某些強制要被定義和實現的方法,可以定義為抽象方法,那么一旦有子類繼承該抽象類,子類就必須要按照契約來實現這個抽象方法。使用abstract有以下幾個需要遵循的原則:抽象類不象具用抽象類來實現之前開關門的業務

現在我們使用抽象類來實現之前的功能。public

abstract

classDoor{public

voidopen(){System.out.println("門開了!");}public

voidclose(){System.out.println("門關了");}}這樣看似在結果上沒有任何變化,但是卻已經符合抽象思維某種角度和語義——就相當于,水果是抽象類,那么蘋果,梨就是具體類,由具體類負責來實例對象,抽象類只負責描述抽象特征和行為。注意:如果一個類繼承了抽象類,但沒有實現它所有的抽象方法,那么這個類也是抽象類。用抽象類來實現之前開關門的業務現在我們使用抽象類來實現之前

在Door抽象類中定義抽象方法:public

abstract

voidtheNo();如果我們現在要求每個門都必須有一個提供自己門牌號的方法——由于每個門的門牌號都不一樣,所以可以定義一個抽象方法,由子類具體實現內容。在子類中實現抽象方法:public

voidtheNo(){System.out.println("我是安全門No2085");}相當于契約。實現契約。在Door抽象類中定義抽象方法:publicabstra7、接口

由于繼承具有單根性,java不支持一個類有多個直接的父類,所以一個類只能繼承一個抽象類。為解決這一問題,Java引入了接口類型,彌補了Java的單繼承的弱點。一個類只能有一個直接的父類,但可以實現多個接口。接口的定義語法:publicinterface

接口名{

}接口只負責定義規則,不負責任何實現。實現交給實現接口的類。7、接口由于繼承具有單根性,java不支持一個類有多個直接

接口有以下特點:1.接口中的成員變量默認都是publicstaticfinal的——即靜態常量。2.接口中的方法都沒有方法體——即可以認為都是抽象方法,但是不需要abstract關鍵字來修飾。3.接口不能實現接口,但可以繼承多個接口。4.接口必須通過他的實現類來實例。public

interfaceUserDAO{int

DEFAULT_COLOR=1;int

RED=2;publicbooleandeleteById(intid);}定義接口:想一想,能不能在接口中定義私有的方法?接口有以下特點:publicinterfaceUser接口的實現類

實現接口:僅僅定義一個接口不去實現,就像定義一個類,但什么都不寫;或者定義一個類,從來都不使用;是沒有什么意義的。所以我們需要為接口編寫實現類。public

classUserDAOImplimplementsUserDAO{public

booleandeleteById(intid){System.out.println("模擬通過id刪除信息!");return

true;}}一個類通過implements關鍵字來實現一個接口,而且必須實現接口中所有的方法。習慣上,對于某個接口的實現類,我們一般命名規則是:接口名+Impl如UserDAOImpl是UserDAO接口的實現類。實現某個接口的類叫做該接口的實現類,而不是子類。接口的實現類實現接口:僅僅定義一個接口不去實現,就像定義一

一般來說,我們在實例抽象類的子類或者接口的實現類的時候,都傾向于這樣的實例方法:抽象類對象名=new子類();接口對象名=new實現類();而不是直接new子類或者實現類。接口和抽象類一樣不能被直接實例化,只能實例化他的實現類。這樣的做法是出于多態的考慮。凡是通過這種方式實例出的對象,都可以認為他的類型就是父類或者接口類。在編寫方法的時候,假如只寫一個方法,將基礎類作為變量或參數使用,而不是使用那些特定的衍生類,那么可以減少很多代碼量。這種自下而上的抽象,就是java中所謂的“上溯造型”。一般來說,我們在實例抽象類的子類或者接口的實現類的時候,都8、抽象類和接口對比

抽象類和接口的主要區別:1.抽象類里面可以為部分方法提供實現;接口只聲明方法,不提供任何實現2.一個類只能繼承一個父類,但可以實現多個接口。接口是構建松耦合的軟件系統的法寶,他只描述服務或者契約,沒有具體的實現,可以實現解耦。所以很多大師級人物都推崇面向接口編程,而不是面向實現編程。從設計模式的角度考慮:應當優先使用對象組合,而不是類繼承。那么到底什么情況下該使用接口,什么情況下使用抽象類呢?我們通過一個實例來進行考究。8、抽象類和接口對比抽象類和接口的主要區別:接口是構建松耦9、接口和抽象類使用場合實例

解決方案1.全部放進抽象類public

abstract

classDoor{public

voidopen(){System.out.println("門開了!");}public

voidclose(){System.out.println("門關了");}public

voidring(){

}}由于繼承抽象類的子類可以使用父類的屬性和方法。所以不管ring方法如何被定義,最終子類都是能拿到的。不符合我們只是有些門具有按門鈴動作的要求。假設,我們現在有些門有開門,關門,按門鈴三個動作,其中開門,關門動作是所有門都有的動作,而按門鈴只是部分門才具有的,那么這三個動作該如何分配呢?9、接口和抽象類使用場合實例解決方案1.全部放進抽象類pu

解決方案2.全部放進接口這里也同樣面臨和抽象類一樣的問題,實現接口就必須實現接口中所有的方法,違反了ISP(接口隔離原則)——不應該強迫客戶程序依賴于它們不用的方法。public

interfaceDoor{

public

voidopen();

public

voidclose();

public

voidring();}那面對這樣的問題,到底該怎么設計呢?解決方案2.全部放進接口這里也同樣面臨和抽象類一樣的問題,

開門和關門動作屬于門本身具有不可卸載或公有的動作,或者說本質功能。按門鈴屬于特殊動作,或者說附加功能。我們應當將這些不可卸載的本質功能定義在抽象類里,將附加功能定義在接口里。這樣,對于有特殊功能的門只需要實現對應的功能接口就好了。//本質功能public

abstract

classDoor{public

voidopen(){

System.out.println("門開了!");

}public

voidclose(){

System.out.println("門關了");

}}//附加功能public

interfaceRingDoor{

public

voidring();}開門和關門動作屬于門本身具有不可卸載或公有的動作,或者說本

普通門:安全門:public

classCommDoorextendsDoor{}public

classSecurityDoorextendsDoorimplementsRingDoor{}普通門只需要繼承Door有附加功能的門可以實現對應功能的接口,即可獲得該功能。這樣如果我們的門還需要有報警功能,那么只需要制定一個報警接口,由具有報警功能的門來具體實現就好了。至此,對于抽象類和接口的使用場合就比較明了了。普通門:安全門:publicclassCommDoorⅡ案例1Ⅱ案例1案例1需求

為學校各中心開發這樣一個小系統,包含類型:教員、中心、打印機,具體要求如下:教員、以及中心都具有方法:輸出詳細信息中心具有屬性:打印機,能夠通過中心的打印機打印教員或中心的詳細信息系統要具備良好的可擴展性與可維護性打印教員中心教員

詳細信息中心

詳細信息detail方法(輸出詳細信息)案例1需求為學校各中心開發這樣一個小系統,包含類型:教解決方案1

思考:這個解決方案中存在著什么問題?publicclassTeacher{//輸出教員的詳細信息publicStringdetail(){ return“本人是計算機老師";}}publicclassSchool{privatePrinterprinter=newPrinter();//輸出中心的詳細信息publicStringdetail(){return“這里是信電學院";}//使用打印機打印教員信息publicvoidprint(Teachert){printer.print(t.detail());}//使用打印機打印學院信息publicvoidprint(Schools){ printer.print(s.detail());}}publicclassPrinter{publicvoidprint(Stringcontent){System.out.println("開始打印:");System.out.println(content);}}每增加一種新類型,都需要增加相應的print(類型名稱var)方法——程序的可擴展性及可維護性極差——這不符合系統的要求解決方案1思考:這個解決方案中存在著什么問題?public解決思路

可以通過多態性解決這個問題嗎?顯然,本系統符合使用多態性的條件教員學院detail方法(負責輸出詳細信息)教員

詳細信息學院

詳細信息1221回顧多態的含義:實現同一個接口,使用不同的實例而執行不同操作解決思路可以通過多態性解決這個問題嗎?顯然,本系統符合使用思考:在這個系統中,存在繼承關系嗎?

教員、中心屬于兩種不同的類型,無法通過“is-a”找到一個合適的父類教員、中心都存在一個共同的方法特征:detail,它們對detail方法有各自不同的實現——這完全符合Java接口的定義定義一個Java接口,在其中定義detail方法,但沒有具體實現實現這個Java接口,不同的類對detail方法有不同的具體實現IntroduceableTeacher(教員)School(學院)思考:在這個系統中,存在繼承關系嗎?教員、中心解決方案2

publicinterfaceIntroduceable{publicStringdetail();}publicclassSchool

implementsIntroduceable{privatePrinterprinter=newPrinter();//輸出學院的詳細信息publicStringdetail(){return“這里是信電學院";}//使用學院打印機打印信息publicvoidprint(Introduceableintro){ printer.print(intro.detail());}}publicclassTeacher

implementsIntroduceable{//輸出教員的詳細信息publicStringdetail(){ return“本人是軟件教員";}}通過Java接口,我們同樣可以享受到多態性的好處,大大提高了程序的可擴展性及可維護性使用print方法時,參數可以是任何Introduceable接口的實現類的對象,不必再為不同的類型建立不同的print方法了思考:使用了Java接口之后,這個系統有了怎樣的改進?解決方案2publicinterfaceIntroduⅡ案例2Ⅱ案例2面向接口編程

什么是面向接口編程開發系統時,主體構架使用接口,接口構成系統的骨架這樣就可以通過更換接口的實現類來更換系統的實現publicclassSchoolimplementsIntroduceable{privatePrinterprinter=newPrinter();publicStringdetail(){return“這里是信電學院";}//使用學院打印機打印信息publicvoidprint(Introduceableintro){ printer.print(intro.detail());}}IntroduceableTeacher(教員)SiyuanSchool(學院)面向接口編程什么是面向接口編程開發系統時,主體構架使用接口案例2需求

升級案例1的系統,要求: 打印機有多種類型,比如:黑白打印機、彩色打印機等

學院可能配備其中任意一款打印機,負責打印教員、或者學院的詳細信息 系統要具備良好的可擴展性與可維護性print方法(打印)彩色打印機黑白打印機黑白內容學院/教員詳細信息彩色內容案例2需求升級案例1的系統,要求:print方法彩色打解決辦法:第一步抽象出Java接口

1、分析:黑白、彩色打印機都存在一個共同的方法特征:print黑白、彩色打印機對print方法有各自不同的實現2、結論:抽象出Java接口PrinterFace,在其中定義方法print3、具體實現:publicinterfacePrinterFace{publicvoid

print(Stringcontent);}解決辦法:第一步抽象出Java接口1、分析:publ解決辦法:第二步實現Java接口

publicclassColorPrinter

implementsPrinterFace{publicvoid

print(Stringcontent){System.out.println("彩色打印:");System.out.println(content);}}publicclassBlackPrinter

implementsPrinterFace{publicvoid

print(Stringcontent){System.out.println("黑白打印:");System.out.println(content);}}1、分析:已經抽象出Java接口PrinterFace,并在其中定義了print方法黑白、彩色打印機對print方法有各自不同的實現2、結論:黑白、彩色打印機都實現PrinterFace接口,各自實現print方法3、具體實現:解決辦法:第二步實現Java接口publicclas解決辦法:第三步使用Java接口

使用Java接口1、分析:主體構架使用接口,讓接口構成系統的骨架2、結論:更換實現接口的類就可以更換系統的實現3、具體實現:publicclassSchoolimplementsIntroduceable{privatePrinterFaceprinter;//打印機

publicvoidsetPrinter(PrinterFacep){this.printer=p;}publicStringdetail(){return“這里是信電學院";}publicvoidprint(Introduceableintro){

printer.print(intro.detail());}}publicclassSiyuanTest{publicstaticvoidmain(String[]args){//創建學院實例

Schoolschool=newSchool();//為該學院配備黑白打印機

school.setPrinter(newBlackPrinter());school.print(school);//為該學院配備彩色打印機

school.setPrinter(new

ColorPrinter());school.print(school);}}解決辦法:第三步使用Java接口使用Java接口pubⅡ案例3Ⅱ案例3項目案例:打字游戲訓練的技能點面向對象設計的思想使用類圖理解類的關系類的封裝構造方法的使用this、static關鍵字的使用項目案例:打字游戲訓練的技能點任務描述需求概述根據輸入速率和正確率將玩家分為不同級別級別越高,一次顯示的字符數越多,玩家正確輸入一次的得分也越高規定時間內完成規定次數的輸入,正確率達到規定要求,則升級玩家最高級別為6級、初始級別一律為1級用戶錯誤輸入一次,游戲結束開發工具JDK6.0、Eclipse任務描述需求概述第一步:分析需要使用到的類分析本案例需要用到的類有哪些:玩家(Player)類游戲(Game)類級別(Level)類第一步:分析需要使用到的類分析本案例需要用到的類有哪些:第二步:分析各個類應該具有哪些屬性玩家類(Player)的屬性玩家當前級別號(levelNo)玩家當前級別積分(currScore)當前級別開始時間(startTime)當前級別已用時間(elapsedTime)游戲類(Game)級別類(Level)的屬性各級別號(levelNo)各級別一次輸出字符串的長度(strLength)各級別輸出字符串的次數(strTime)各級別闖關的時間限制(timeLimit)各級別正確輸入一次的得分(perScore)第二步:分析各個類應該具有哪些屬性玩家類(Player)的屬第三步:分析各個類應該具有哪些方法玩家類(Player)的方法玩游戲play()游戲類(Game)的方法StringprintStr()產生并輸出字符串,返回字符串用于和玩家輸入比較。voidlogic(Stringout,Stringin)比較游戲輸出out和玩家輸入in,根據比較結果輸出相應信息第三步:分析各個類應該具有哪些方法玩家類(Player)的方第四步:審核以上設計,并優化設計修改游戲類(Game),添加屬性玩家:Player添加類:LevelParampublicfinalstaticLevellevel[6]第四步:審核以上設計,并優化設計修改游戲類(Game),添加第五步:主要功能分析游戲輸出字符串生成字符串、輸出字符串、返回字符串生成長度固定但內容隨機的字符串確認輸入并輸出結果輸入正確、未超時輸出當前級別、當前積分、已用時間計算玩家的當前級別、當前積分和已用時間玩游戲6個級別循環實現每次晉級后積分清零、計時清零第五步:主要功能分析游戲輸出字符串功能流程分析游戲根據玩家的級別在控制臺輸出指定數量字符玩家根據控制臺輸出來輸入相同字符,回車確認確認玩家輸入是否正確如果輸入錯誤,輸出輸入錯誤提示,游戲非正常結束如果輸入正確但超時,輸出玩家速度太慢提示,游戲非正常結束如果輸入正確且沒有超時,輸出玩家的積分、級別和用時信息。繼續以上操作規定時間內連續正確輸入規定次數,顯示升級提示;游戲重新計時計分,將一次輸出更多字符。6級玩家闖關成功,輸出恭喜信息,游戲正常結束功能流程分析游戲根據玩家的級別在控制臺輸出指定數量字符開發方案1:游戲輸出字符串2:確認輸入并輸出結果3:玩家玩游戲4:初始化各個級別的具體參數開發方案1:游戲輸出字符串1.在控制臺輸出隨機字符串思路分析生成字符串輸出字符串返回字符串難點提示Game類中的player屬性,代表玩家,查詢player的級別號,然后根據級別號到LevelParam類中獲取該級別的字符串長度字符串長度固定可以通過for循環來實現,而隨機內容可以通過獲取隨機數,而不同隨機數對應不同字符來實現 1.在控制臺輸出隨機字符串思路分析Game中的方法

StringBufferbuffer=newStringBuffer();Randomrandom=newRandom();//1、通過循環生成要輸出的字符串for(inti=0;i<strLength;i++){ //1.1、產生隨機數

intrand=random.nextInt(127); //1.2、根據隨機數拼接字符串buffer.append(char(rand));}互相測試完成的程序功能測試出的缺陷記錄在“常見問題列表中”單元測試StringprintStr()產生并輸出字符串,返回字符串用于和玩家輸入比較。Game中的方法StringBufferbuffer=2、確認用戶輸入并輸出結果思路分析確認玩家輸入是否正確如果輸入不正確,則直接輸出錯誤信息并退出程序如果輸入正確如果超時,則直接輸出錯誤信息并退出程序;如果沒有超時計算玩家當前積分;計算玩家已用時間;輸出玩家當前級別、當前積分、已用時間;判斷用戶是否已經闖過最后一關并處理2、確認用戶輸入并輸出結果思路分析Game中的方法

longcurrentTime=System.currentTimeMillis();//如果超時if((currentTime-player.getStartTime())/1000>LevelParam.levels[player.getLevelNo()-1].getTimeLimit()){ System.out.println("你輸入太慢了,已經超時,退出!"); System.exit(1);}//計算玩家當前積分player.setCurScore(player.getCurScore() +LevelParam.levels[player.getLevelNo()-1].getPerScore());voidprintResult(Stringout,Stringin)比較游戲輸出out和玩家輸入in,根據比較結果輸出相應信息Game中的方法longcurrentTime=Sy3、玩家玩游戲思路分析創建Game對象并傳入player屬性;外層循環(循環次數是6,每循環一次玩家級別升一級)晉級;積分清零、計時清零;內層循環(循環次數是該級別的strTime,每循環一次完成一次人機交互)游戲輸出字符串;玩家輸入字符串;游戲判斷玩家輸入并輸出相應結果。3、玩家玩游戲思路分析4、游戲開始之前初始化各個級別的具體參數信息游戲參數設置如各級別號各級別一次輸出字符串的長度各級別輸出字符串的次數各級別闖關的時間限制各級別正確輸入一次的得分難點分析使用static修飾屬性和代碼塊static屬性屬于這個類所有通過“對象名.static屬性名”、“類名.static屬性名”訪問static方法通過“類名.static方法名”和“對象名.static方法名”訪問static代碼塊主要作用是實現static屬性的初始化當類被載入的時候執行它,且只被執行一次4、游戲開始之前初始化各個級別的具體參數信息游戲參數設置

classStaticCodeBlock{ staticStringname="defname"; static{ name="staticname"; System.out.println("executestaticcodeblock"); } publicStaticCodeBlock(){ System.out.println("executeconstructor"); }}publicclassTestStaticCodeBlock{ static{ System.out.println("executestaticcodeblockinTest"); } publicstaticvoidmain(String[]args){ System.out.println("executemain()"); newStaticCodeBlock(); newStaticCodeBlock(); newStaticCodeBlock(); }}static舉例說明classStaticCodeBlock{static

publicclassLevelParam{ publicfinalstaticLevellevels[]=newLevel[6];//對應六個級別

static{ levels[0]=newLevel(1,2,10,30,1); levels[1]=newLevel(2,3,9,26,2); levels[2]=newLevel(3,4,8,22,5); levels[3]=newLevel(4,5,7,18,8); levels[4]=newLevel(5,6,6,15,10); levels[5]=newLevel(6,7,5,12,15); }}示例代碼publicclassLevelParam{示例代碼

講解要點:完成情況、技能總結、經驗分享、項目收獲表達要求:清晰流暢、有條理、重點突出項目展示講解要點:項目展示面向對象核心內容回顧及案例分析面向對象核心內容回顧及案例分析Ⅰ內容回顧Ⅰ內容回顧內容回顧列表1.繼承及繼承實例2.方法重寫(Overwrite)3.super關鍵字4.方法重載(Overload)5.final修飾符6.abstract修飾符7.抽象類8.接口9.接口和抽象類對比10.接口和抽象類使用場合實例內容回顧列表1.繼承及繼承實例1、繼承

剛開始講繼承的時候,我們就已經初始了繼承的概念:子類自動共享父類數據結構和方法的機制,這是類之間的一種關系。繼承也是提高代碼復用的有力手段,當多個類之間存在相同的屬性和方法時,就可以考慮繼承,從這些類中抽象出父類——在父類中定義這些相同的屬性和方法,子類無需再定義這些相同的屬性和方法,只需要通過extends語句來聲明繼承關系即可:繼承具有單根性:即一個類只能繼承最多一個類。不能出現:publicclassSonextends

Base,Base2{……}但是Base類可以繼承其他類。publicclassSonextendsBase{……}son:代表子類,又叫做超類。Base:代表父類,又叫做基類。1、繼承剛開始講繼承的時候,我們就已經初始了繼承的概念:繼繼承案例分析:門

所有門都擁有開(open)和關(close)這樣的動作,不管是普通的門還是安全門,所以我們這里定義一個公用的父類Door類,并且默認的認為所有的門的名字都叫門。public

classDoor{publicStringdoorName="門";//門的名字public

voidopen(){//開門方法System.out.println("門開了!");}public

voidclose(){//關門方法System.out.println("門關了");}}創建父類Door繼承案例分析:門所有門都擁有開(open)和關(close創建子類——CommonDoor和SecurityDoor

public

classCommDoorextendsDoor{}普通門CommDoor:public

classSecurityDoorextendsDoor{}安全門:創建子類——CommonDoor和SecurityDoor繼承測試

可以發現,在CommDoor和SecurityDoor中我們一行代碼都沒有寫,只是繼承了Door類,就可以直接使用open和close方法了。這正是繼承的特點——子類可以共享父類的數據和方法。public

static

voidmain(String[]args){CommDoorcd=newCommDoor();System.out.println(cd.doorName);cd.open();cd.close();SecurityDoorsd=newSecurityDoor();System.out.println(sd.doorName);sd.open();sd.close();}結果:如果說類的數量很多,那么這種優勢就更加顯而易見了。但是繼承的弱點是:打破了封裝,當父類一旦改變,子類也就可能發生變化,類的耦合度過高,不符合我們高內聚低耦合的設計原則。繼承測試可以發現,在CommDoor和SecurityDo2、方法重寫(Overwrite)

方法重寫(Overwrite)又叫方法覆蓋(Override),是有繼承關系的類之間的一種多態特性。如果,對于一般門,當調用open方的時候直接輸出“門開了”就好了,可是對于安全門我們可能在開門之前需要做一個身份驗證,以確定是否真的要開門。那么我們就需要在子類里面重寫父類的open方法。public

voidopen(){System.out.println("/*--安全門,模擬執行了安全驗證--*/");System.out.println("門開了!");}這種在子類中重新定義父類已有方法的行為就是重寫,重寫是多態的一種體現形式。2、方法重寫(Overwrite)方法重寫(Overwri3、super關鍵字

一般在以下情況我們會用到super關鍵字:1.在子類構造方法中,通過super調用父類構造方法2.在子類中訪問父類被覆蓋重寫的方法和屬性現在給Door添加構造方法,如下:publicDoor(StringdoorName){this.doorName=doorName;}在SecurityDoor中可以如下定義:publicSecurityDoor(StringdoorName,Stringbrand){super(doorName);this.brand=brand;}這里的super代表調用父類的構造方法。說明,SecurityDoor有一個自己的brand屬性。3、super關鍵字一般在以下情況我們會用到super關鍵3、super關鍵字

如果在子類中重寫了父類屬性,如在Security中重新定義了doorName屬性:privateStringdoorName="安全門";要想再訪問到父類的屬性,則可以使用:super.doorName;測試:System.out.println(this.doorName+""+super.doorName);結果:3、super關鍵字如果在子類中重寫了父類屬性,如在Sec4、方法重載(Overload)

方法重載(Overload),是類的同一功能(方法)有多種實現方式。其實重載在學習Math數學類的時候已經有所接觸了,如下:這里有四個都叫max的方法,但是他們的參數列表不同,這樣就可以實現,當我們不論輸入任何兩個數字型(double,int,float,long)的參數的時候,都能返回最大值。不需要定義doubleMax,floatMax,intMax,longMax這樣的方法。4、方法重載(Overload)方法重載(Overload

假設,我們的安全門現在有多種開門方式,可以使用鑰匙開門,使用6位密碼開門,輸入房號和訪客姓名請求開門三種方式。那么我們可以做如下定義:public

void

open(Stringkey){System.out.println("/*--用鑰匙開安全門,模擬驗證鑰匙是否正確--*/");System.out.println("門開了!");}public

void

open(int

pwd){System.out.println("/*--用6位密碼開門,模擬驗證密碼是否正確--*/");System.out.println("門開了!");}public

void

open(int

doorNo,StringvisitName){System.out.println("/*--"+visitName+"請求"+doorNo+"開門,模擬確定是否開門--*/");System.out.println("門開了!");}不允許僅僅返回值不同的重載。如:publicvoidopen(Stringkey){……}和publicStringopen(Stringkey){……}是不能通過編譯的。重載的特點:方法名都相同,參數列表不同。假設,我們的安全門現在有多種開門方式,可以使用鑰匙開門,使5、final修飾符

final修飾符可以修飾類,變量,方法。被final修飾的變量叫做常量,值不能被修改,如finalintPI=3.14;被final修飾的類不能被繼承。被final修飾的方法不能被重寫。5、final修飾符final修飾符可以修飾類,變量,方法6、abstract修飾符

abstract修飾符可以修飾類,方法。被abstract修飾的類叫做抽象類,抽象類不能被實例化。被abstract修飾的方法叫做抽象方法,抽象方法沒有方法體,不提供具體實現。public

abstract

classDoor{public

abstract

voidopen();}所謂不能實例,就是指不能:Doordoor=newDoor();所謂無方法體,不實現就是指:open方法沒有具體的指定實現。那么定義這樣的類和方法有什么用呢?我們最終當然要為這樣的類和方法提供一個實現,這個實現就是繼承他的類,他的子類可以為抽象方法提供具體的實現。抽象類通常代表一個抽象概念,可以用一句話來概括抽象類的用途:抽象類是用來繼承的。反過來可以說具體類不是用來繼承的,只要有可能,我們不要從具體類繼承——之前我們的做法雖然實現了功能,但是沒有達到思想上的真正意義。6、abstract修飾符abstract修飾符可以修飾類

使用abstract有以下幾個需要遵循的原則:抽象類中可以沒有抽象方法,但包含抽象方法的類就必須是抽象類。抽象方法不能是靜態的。抽象類及抽象方法不能被final修飾。抽象類不象具體類那樣描述一類具體事物,它是提取多種具有相似性的具體事物的共同特征而產生的。而不是一個具體描述對象的類。同時抽象類和抽象方法其實是面向契約的一種體現,抽象類就相當于一個制定者。對于某些強制要被定義和實現的方法,可以定義為抽象方法,那么一旦有子類繼承該抽象類,子類就必須要按照契約來實現這個抽象方法。使用abstract有以下幾個需要遵循的原則:抽象類不象具用抽象類來實現之前開關門的業務

現在我們使用抽象類來實現之前的功能。public

abstract

classDoor{public

voidopen(){System.out.println("門開了!");}public

voidclose(){System.out.println("門關了");}}這樣看似在結果上沒有任何變化,但是卻已經符合抽象思維某種角度和語義——就相當于,水果是抽象類,那么蘋果,梨就是具體類,由具體類負責來實例對象,抽象類只負責描述抽象特征和行為。注意:如果一個類繼承了抽象類,但沒有實現它所有的抽象方法,那么這個類也是抽象類。用抽象類來實現之前開關門的業務現在我們使用抽象類來實現之前

在Door抽象類中定義抽象方法:public

abstract

voidtheNo();如果我們現在要求每個門都必須有一個提供自己門牌號的方法——由于每個門的門牌號都不一樣,所以可以定義一個抽象方法,由子類具體實現內容。在子類中實現抽象方法:public

voidtheNo(){System.out.println("我是安全門No2085");}相當于契約。實現契約。在Door抽象類中定義抽象方法:publicabstra7、接口

由于繼承具有單根性,java不支持一個類有多個直接的父類,所以一個類只能繼承一個抽象類。為解決這一問題,Java引入了接口類型,彌補了Java的單繼承的弱點。一個類只能有一個直接的父類,但可以實現多個接口。接口的定義語法:publicinterface

接口名{

}接口只負責定義規則,不負責任何實現。實現交給實現接口的類。7、接口由于繼承具有單根性,java不支持一個類有多個直接

接口有以下特點:1.接口中的成員變量默認都是publicstaticfinal的——即靜態常量。2.接口中的方法都沒有方法體——即可以認為都是抽象方法,但是不需要abstract關鍵字來修飾。3.接口不能實現接口,但可以繼承多個接口。4.接口必須通過他的實現類來實例。public

interfaceUserDAO{int

DEFAULT_COLOR=1;int

RED=2;publicbooleandeleteById(intid);}定義接口:想一想,能不能在接口中定義私有的方法?接口有以下特點:publicinterfaceUser接口的實現類

實現接口:僅僅定義一個接口不去實現,就像定義一個類,但什么都不寫;或者定義一個類,從來都不使用;是沒有什么意義的。所以我們需要為接口編寫實現類。public

classUserDAOImplimplementsUserDAO{public

booleandeleteById(intid){System.out.println("模擬通過id刪除信息!");return

true;}}一個類通過implements關鍵字來實現一個接口,而且必須實現接口中所有的方法。習慣上,對于某個接口的實現類,我們一般命名規則是:接口名+Impl如UserDAOImpl是UserDAO接口的實現類。實現某個接口的類叫做該接口的實現類,而不是子類。接口的實現類實現接口:僅僅定義一個接口不去實現,就像定義一

一般來說,我們在實例抽象類的子類或者接口的實現類的時候,都傾向于這樣的實例方法:抽象類對象名=new子類();接口對象名=new實現類();而不是直接new子類或者實現類。接口和抽象類一樣不能被直接實例化,只能實例化他的實現類。這樣的做法是出于多態的考慮。凡是通過這種方式實例出的對象,都可以認為他的類型就是父類或者接口類。在編寫方法的時候,假如只寫一個方法,將基礎類作為變量或參數使用,而不是使用那些特定的衍生類,那么可以減少很多代碼量。這種自下而上的抽象,就是java中所謂的“上溯造型”。一般來說,我們在實例抽象類的子類或者接口的實現類的時候,都8、抽象類和接口對比

抽象類和接口的主要區別:1.抽象類里面可以為部分方法提供實現;接口只聲明方法,不提供任何實現2.一個類只能繼承一個父類,但可以實現多個接口。接口是構建松耦合的軟件系統的法寶,他只描述服務或者契約,沒有具體的實現,可以實現解耦。所以很多大師級人物都推崇面向接口編程,而不是面向實現編程。從設計模式的角度考慮:應當優先使用對象組合,而不是類繼承。那么到底什么情況下該使用接口,什么情況下使用抽象類呢?我們通過一個實例來進行考究。8、抽象類和接口對比抽象類和接口的主要區別:接口是構建松耦9、接口和抽象類使用場合實例

解決方案1.全部放進抽象類public

abstract

classDoor{public

voidopen(){System.out.println("門開了!");}public

voidclose(){System.out.println("門關了");}public

voidring(){

}}由于繼承抽象類的子類可以使用父類的屬性和方法。所以不管ring方法如何被定義,最終子類都是能拿到的。不符合我們只是有些門具有按門鈴動作的要求。假設,我們現在有些門有開門,關門,按門鈴三個動作,其中開門,關門動作是所有門都有的動作,而按門鈴只是部分門才具有的,那么這三個動作該如何分配呢?9、接口和抽象類使用場合實例解決方案1.全部放進抽象類pu

解決方案2.全部放進接口這里也同樣面臨和抽象類一樣的問題,實現接口就必須實現接口中所有的方法,違反了ISP(接口隔離原則)——不應該強迫客戶程序依賴于它們不用的方法。public

interfaceDoor{

public

voidopen();

public

voidclose();

public

voidring();}那面對這樣的問題,到底該怎么設計呢?解決方案2.全部放進接口這里也同樣面臨和抽象類一樣的問題,

開門和關門動作屬于門本身具有不可卸載或公有的動作,或者說本質功能。按門鈴屬于特殊動作,或者說附加功能。我們應當將這些不可卸載的本質功能定義在抽象類里,將附加功能定義在接口里。這樣,對于有特殊功能的門只需要實現對應的功能接口就好了。//本質功能public

abstract

classDoor{public

voidopen(){

System.out.println("門開了!");

}public

voidclose(){

System.out.println("門關了");

}}//附加功能public

interfaceRingDoor{

public

voidring();}開門和關門動作屬于門本身具有不可卸載或公有的動作,或者說本

普通門:安全門:public

classCommDoorextendsDoor{}public

classSecurityDoorextendsDoorimplementsRingDoor{}普通門只需要繼承Door有附加功能的門可以實現對應功能的接口,即可獲得該功能。這樣如果我們的門還需要有報警功能,那么只需要制定一個報警接口,由具有報警功能的門來具體實現就好了。至此,對于抽象類和接口的使用場合就比較明了了。普通門:安全門:publicclassCommDoorⅡ案例1Ⅱ案例1案例1需求

為學校各中心開發這樣一個小系統,包含類型:教員、中心、打印機,具體要求如下:教員、以及中心都具有方法:輸出詳細信息中心具有屬性:打印機,能夠通過中心的打印機打印教員或中心的詳細信息系統要具備良好的可擴展性與可維護性打印教員中心教員

詳細信息中心

詳細信息detail方法(輸出詳細信息)案例1需求為學校各中心開發這樣一個小系統,包含類型:教解決方案1

思考:這個解決方案中存在著什么問題?publicclassTeacher{//輸出教員的詳細信息publicStringdetail(){ return“本人是計算機老師";}}publicclassSchool{privatePrinterprinter=newPrinter();//輸出中心的詳細信息publicStringdetail(){return“這里是信電學院";}//使用打印機打印教員信息publicvoidprint(Teachert){printer.print(t.detail());}//使用打印機打印學院信息publicvoidprint(Schools){ printer.print(s.detail());}}publicclassPrinter{publicvoidprint(Stringcontent){System.out.println("開始打印:");System.out.println(content);}}每增加一種新類型,都需要增加相應的print(類型名稱var)方法——程序的可擴展性及可維護性極差——這不符合系統的要求解決方案1思考:這個解決方案中存在著什么問題?public解決思路

可以通過多態性解決這個問題嗎?顯然,本系統符合使用多態性的條件教員學院detail方法(負責輸出詳細信息)教員

詳細信息學院

詳細信息1221回顧多態的含義:實現同一個接口,使用不同的實例而執行不同操作解決思路可以通過多態性解決這個問題嗎?顯然,本系統符合使用思考:在這個系統中,存在繼承關系嗎?

教員、中心屬于兩種不同的類型,無法通過“is-a”找到一個合適的父類教員、中心都存在一個共同的方法特征:detail,它們對detail方法有各自不同的實現——這完全符合Java接口的定義定義一個Java接口,在其中定義detail方法,但沒有具體實現實現這個Java接口,不同的類對detail方法有不同的具體實現IntroduceableTeacher(教員)School(學院)思考:在這個系統中,存在繼承關系嗎?教員、中心解決方案2

publicinterfaceIntroduceable{publicStringdetail();}publicclassSchool

implementsIntroduceable{privatePrinterprinter=newPrinter();//輸出學院的詳細信息publicStringdetail(){return“這里是信電學院";}//使用學院打印機打印信息publicvoidprint(Introduceableintro){ printer.print(intro.detail());}}publicclassTeacher

implementsIntroduceable{//輸出教員的詳細信息publicStringdetail(){ return“本人是軟件教員";}}通過Java接口,我們同樣可以享受到多態性的好處,大大提高了程序的可擴展性及可維護性使用print方法時,參數可以是任何Introduceable接口的實現類的對象,不必再為不同的類型建立不同的print方法了思考:使用了Java接口之后,這個系統有了怎樣的改進?解決方案2publicinterfaceIntroduⅡ案例2Ⅱ案例2面向接口編程

什么是面向接口編程開發系統時,主體構架使用接口,接口構成系統的骨架這樣就可以通過更換接口的實現類來更換系統的實現publicclassSchoolimplementsIntroduceable{privatePrinterprinter=newPrinter();publicStringdetail(){return“這里是信電學院";}//使用學院打印機打印信息publicvoidprint(Introduceableintro){ printer.print(intro.detail());}}IntroduceableTeacher(教員)SiyuanSchool(學院)面向接口編程什么是面向接口編程開發系統時,主體構架使用接口案例2需求

升級案例1的系統,要求: 打印機有多種類型,比如:黑白打印機、彩色打印機等

學院可能配備其中任意一款打印機,負責打印教員、或者學院的詳細信息 系統要具備良好的可擴展性與可維護性print方法(打印)彩色打印機黑白打印機黑白內容學院/教員詳細信息彩色內容案例2需求升級案例1的系統,要求:print方法彩色打解決辦法:第一步抽象出Java接口

1、分析:黑白、彩色打印機都存在一個共同的方法特征:print黑白、彩色打印機對print方法有各自不同的實現2、結論:抽象出Java接口PrinterFace,在其中定義方法print3、具體實現:publicinterfacePrinterFace{publicvoid

print(Stringcontent);}解決辦法:第一步抽象出Java接口1、分析:publ解決辦法:第二步實現Java接口

publicclassColorPrinter

implementsPrinterFace{publicvoid

print(Stringcontent){System.out.println("彩色打印:");System.out.println(content);}}publicclassBlackPrinter

implementsPrinterFace{publicvoid

print(Stringcon

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論