面向?qū)ο蠹夹g(shù)(Java)課件第3章 面向?qū)ο蠡驹砗蚃ava實現(xiàn)_第1頁
面向?qū)ο蠹夹g(shù)(Java)課件第3章 面向?qū)ο蠡驹砗蚃ava實現(xiàn)_第2頁
面向?qū)ο蠹夹g(shù)(Java)課件第3章 面向?qū)ο蠡驹砗蚃ava實現(xiàn)_第3頁
面向?qū)ο蠹夹g(shù)(Java)課件第3章 面向?qū)ο蠡驹砗蚃ava實現(xiàn)_第4頁
面向?qū)ο蠹夹g(shù)(Java)課件第3章 面向?qū)ο蠡驹砗蚃ava實現(xiàn)_第5頁
已閱讀5頁,還剩38頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

課堂目標(biāo)理解面向?qū)ο笤O(shè)計的基本概念和原理掌握如何設(shè)計類和創(chuàng)建對象掌握J(rèn)ava中的引用和引用變量掌握方法的重載原理掌握構(gòu)造方法、this關(guān)鍵字的含義理解toString方法、equals方法、getter和setter方法等進一步理解垃圾回收機制在面向?qū)ο蟪绦蛟O(shè)計中,我們可以從大量的客觀實際對象當(dāng)中抽象出一個個代碼類,類中有描述對象內(nèi)部結(jié)構(gòu)狀態(tài)的數(shù)據(jù)編碼部分,還有描述此對象具有的功能和行為的指令編碼部分。而在計算機進程中對象又是類的具體化實例,用一個設(shè)計好的類可以創(chuàng)建許多對象。簡單說類就是對象的代碼抽象(包括數(shù)據(jù)和指令),是創(chuàng)建對象的代碼模板,對象是類的具體化的實例,類似生命世界中DNA編碼和生命體的關(guān)系。對象較結(jié)構(gòu)化程序設(shè)計中講到的函數(shù)、過程更有邏輯意義,人類認(rèn)識世界就是從一個個基本的實際對象開始的,所以面向?qū)ο蟪绦蛟O(shè)計具有現(xiàn)實的認(rèn)知基礎(chǔ)。面向?qū)ο蟪绦蛟O(shè)計數(shù)據(jù)代碼指令代碼=++能量面向?qū)ο罄碚撜J(rèn)為:系統(tǒng)中一切皆為對象;對象是屬性及其操作的封裝體;對象可按其性質(zhì)劃分為類,對象成為類的實例;實例關(guān)系和繼承關(guān)系是對象之間的靜態(tài)關(guān)系;消息傳遞是對象之間動態(tài)聯(lián)系的唯一形式,也是計算的唯一形式。對象和類是面向?qū)ο蟪绦蛟O(shè)計的核心概念,程序員使用對象和類進行程序設(shè)計。類可以分成兩種,一種是程序員可以直接使用的類,是由JDK提供的或其他人寫好的;另一種需要程序員自行設(shè)計。設(shè)計一個類大致可分為兩步:要對現(xiàn)實世界的實體或系統(tǒng)進行抽象,抽取其合適的狀態(tài)和行為,形成思維中的類;用Java語言來描述思維中的類,使思維中的類成為Java的類。java面向?qū)ο蟪绦蛟O(shè)計要點理解面向?qū)ο缶幊虒ο罂梢员硎粳F(xiàn)實世界中某個具體的事物、系統(tǒng),也可以表示抽象的過程或概念。對象具有兩方面的含義:是一個可以從其賴以存在的“系統(tǒng)”中分離的“個體”有可以“觀察”的數(shù)據(jù)部分和可以“交互”的功能部分組合而成。對象作為一個可以顯現(xiàn)給外圍系統(tǒng)的一個實例,既是構(gòu)成外圍系統(tǒng)小元素,也是具有獨立存在和演化的小系統(tǒng)。類和對象的關(guān)系類是具有共同數(shù)據(jù)和程序的對象抽象,是創(chuàng)建實例對象的代碼模板。類可以理解為代碼的一種存儲狀態(tài),通過實例對象(運行狀態(tài))進入進程世界??深惐菵NA編碼對象可理解為進程中的一個有時空概念的實例,類似于生命體。對象屬性或狀態(tài)操作或行為類抽象實例化數(shù)據(jù)或變量方法封裝的實體=數(shù)據(jù)(物質(zhì)組成)+方法(功能)汽車對象和類既有區(qū)別又有聯(lián)系,類是創(chuàng)建實例對象的代碼模板,而對象則是在進程中按照類模板創(chuàng)建出來的一個個實例,有點像汽車的設(shè)計圖紙和汽車的關(guān)系。采用面向?qū)ο蟪绦蛟O(shè)計技術(shù)的原因主要有兩個,其一是我們認(rèn)識世界研究乃至于改造世界都是以“對象”為基本單位而進行的,我們將這一人類活動衍生到計算機編程中來順理成章;其二是為了提高程序設(shè)計的效率,尤其是在越來越復(fù)雜問題環(huán)境中,解決模塊的顆粒度問題,既內(nèi)聚性和耦合性的分界線問題。類設(shè)計語法成員變量(用來描述對象的屬性):[修飾符]類型變量名[=初值][,變量名[=初值]…];說明:(1)類型:可以是Java的基本類型,如int,float等,也可以是復(fù)雜類型,如我們自己定義的類,或者數(shù)組、接口等。(2)變量名:必須是合法的Java標(biāo)識符。(3)修飾符:說明變量的訪問權(quán)限和某些使用規(guī)則??梢允莗ublic,private,protected,static,final等,后面會一一講到。(4)當(dāng)成員變量含有自己的初始化表達式時,可以對變量初始化,即賦初值。成員方法(用來描述對象的行為):[修飾符]返回類型方法名([形式參數(shù)列表])[throws異常列表]{方法體}說明:(1)返回類型:說明此方法執(zhí)行完后會返回一個值,這里指的是返回值的數(shù)據(jù)類型,可以是基本類型,也可以是復(fù)雜類型。如果返回類型為void,表示返回值為null,既不返回任何值。(2)方法名:方法的名稱,必須是合法的Java標(biāo)識符。(3)形式參數(shù)列表:說明使用此方法所需要的參數(shù)列表,可以有0個或多個,多個參數(shù)間用逗號“,”隔開。在方法執(zhí)行時,調(diào)用者會將調(diào)用時的實際參數(shù)值復(fù)制(傳遞)一份到形參變量中(也稱按值傳遞),傳遞過程是按照順序依次對應(yīng)傳遞的。(4)修飾符:同前面變量,說明此方法的訪問權(quán)限和某些使用規(guī)則。可以是public,private,protected,static,abstract和final等。(5)方法體:用一對花括號“{}”括起來,包含局部變量定義和相應(yīng)的執(zhí)行語句。(6)異常列表:說明本方法有可能產(chǎn)生的異常,需要調(diào)用者處理,后面會詳細(xì)講。成員變量(屬性)和成員方法(行為)消息(即方法調(diào)用)哲學(xué)上不存在孤立系統(tǒng),同樣程序不存在孤立對象,通過許多對象相互作用,可以實現(xiàn)高層次的操作和更復(fù)雜的功能。對象之間的相互作用是通過消息實現(xiàn)的一個消息通常由三部分組成:接受消息對象的名稱要執(zhí)行方法的名稱方法需要的參數(shù)消息的本質(zhì)其實是方法調(diào)用

Studentstu=newStudent(“10001”,“張三”);

stu.moveto(“蘭州”);//給stu發(fā)消息引用類型進階s1s210001astring10001classMydate{intyear;intmonth;intday;}

Mydatetoday=newMyDate()00010008todays2=s1;s1=newString(“astring”);Example:

Strings1;Strings2;基本變量vs引用變量

25a3000inta=25;

200495yearmonthdayMyDatedt=newMyDate();5000dt50004000對象引用作為參數(shù)classTest{inta,b;

Test(inti,intj){a=i;b=j;}//可以在方法中改變對象狀態(tài)

voidchange(Testobj){obj.a=50;obj.b=40;}}

當(dāng)對象作為方法參數(shù)時,在方法中只能改變該對象的狀態(tài),但不能改變該對象的引用voidswapobj(Datex,Datey){

Datetemp=y;y=x;x=temp;}

引用本身按值傳遞Date2002,5,30Date2003,7,23obj1obj2調(diào)用swapobj(obj1,obj2)可改變對象狀態(tài)xyxyimportjava.util.Scanner;publicclassComplexextendsObjectimplementsCloneable{privatedoublerealpart;privatedoubleimaginarypart;publicComplex(){realpart=0;imaginarypart=0;}//默認(rèn)構(gòu)造方法publicComplex(doubles,doublex){realpart=s;imaginarypart=x;}//構(gòu)造方法publicvoidinputme(){Scannerkeyin=newScanner(System.in);System.out.print("real:");realpart=keyin.nextDouble();System.out.print("imaginary:");imaginarypart=keyin.nextDouble();}publicvoidprintme(){Stringstr=""+realpart;if(imaginarypart<0.0)str=str+imaginarypart+"i";elsestr=str+"+"+imaginarypart+"i";System.out.println(str);}}復(fù)數(shù)類Complex示例構(gòu)造方法對象是類實例化后的產(chǎn)物,所謂實例化是按照類的設(shè)計創(chuàng)造對象的過程,就是給此對象分配內(nèi)存空間并初始化,即要進行一系列的構(gòu)造工作,使其變成一個合適的、可用的對象,這就是構(gòu)造方法所完成的工作,類似于現(xiàn)實世界中動物對象的分娩或孵化過程。l構(gòu)造方法是類中一個特殊的方法,特殊之處在于此方法第一要與類名同名,第二方法不能有返回類型。l構(gòu)造方法不能有返回類型并不能代表它不能有返回值,實際上它要返回對象在內(nèi)存中的開始地址。l構(gòu)造方法可以重載,并且我們把沒有任何參數(shù)的構(gòu)造方法稱為默認(rèn)構(gòu)造方法。如前例中的Complex()是默認(rèn)構(gòu)造方法,而Complex(doubles,doublex)則是帶有兩個形參的構(gòu)造方法。創(chuàng)建對象使用下列語法可創(chuàng)建對象:

new構(gòu)造方法關(guān)鍵字new通常稱為創(chuàng)建運算符,用于分配對象內(nèi)存,并將該內(nèi)存初始化為缺省值。一旦new完成分配和初始化內(nèi)存,它就將調(diào)用構(gòu)造方法來執(zhí)行對象初始化。創(chuàng)建對象后沒有引用變量指向它,則為匿名對象,如:newComplex(3.0,5.0).printme();//創(chuàng)建匿名對象并調(diào)用printme方法當(dāng)創(chuàng)建一個類時,只是創(chuàng)建了一種新的數(shù)據(jù)類型。對象是類的一個實例。publicclassTesstComplex{publicstaticvoidmain(String[]args){Complexm1=newComplex(3.4,8.0);m1.inputme();//調(diào)用inputme()方法,即給m1對象發(fā)輸入請求的消息m1.printme();//調(diào)用printme()方法,即給m1對象發(fā)打印輸出的消息}}創(chuàng)建對象對象創(chuàng)建后成員變量初始值Java保證了在任何代碼使用該內(nèi)存之前,已至少將內(nèi)存初始化為可預(yù)知的缺省值類型缺省值類型缺省值byte(byte)0char'\u0000'short(short)0float0.0Fint0double0.0Dlong0L對象引用nullbooleanfalsethis關(guān)鍵字publicclassPassTest{

intx;PassTest(intx){

this.x=x;}publicvoidpassingValue(){System.out.println(“x等于"+x);

}publicstaticvoidmain(Stringargs[]){PassTesttest=newPassTest(10);test.passingValue(); }}

關(guān)鍵字this與對象關(guān)聯(lián)它是引用用于指示當(dāng)前對象指明此對象的變量x應(yīng)賦值為通過構(gòu)造函數(shù)傳遞的自變量x的值。

方法重載(overloading)方法重載是Java實現(xiàn)面向?qū)ο蟮亩鄳B(tài)性機制的一種方式。同一個類中多個方法有相同的名字,不同的參數(shù)列表,這種情況稱為方法重載。返回類型不同并不足以構(gòu)成方法重載,必須還要有參數(shù)不同。當(dāng)重載方法被調(diào)用時,編譯器根據(jù)參數(shù)的類型和數(shù)量來確定實際調(diào)用哪個重載方法的版本。方法重載是靜態(tài)綁定的,即在編譯時,已確定好要執(zhí)行的方法代碼。方法重載示例classCalculation{ publicvoidadd(inta,intb){ intc=a+b; System.out.println("兩個整數(shù)相加得"+c); } publicvoidadd(floata,floatb){ floatc=a+b; System.out.println("兩個浮點數(shù)相加得"+c); } publicvoidadd(Stringa,Stringb){ Stringc=a+b; System.out.println("兩個字符串相加得"+c); } publicvoidadd(Complexa,Complexb){ Complex1f1=newComplex1(a.shibu+b.shibu,a.xubu+b.xubu); System.out.println("兩個復(fù)數(shù)相加得"+f); }}publicclassCalculationDemo{ publicstaticvoidmain(Stringargs[]){ Calculationc=newCalculation(); c.add(10,20); c.add(40.0F,35.65F); c.add("早上","好"); Complexf1=newComplex(3.4,2.8); Complexf2=newComplex(1.6,-7.8); f1.display(); f2.display(); c.add(f1,f2); }}編譯器決定調(diào)用版本Complex1為復(fù)數(shù)類的進化版,參看教材19重載構(gòu)造方法如果程序員沒有提供構(gòu)造方法,Java會為類自動提供一個缺省構(gòu)造方法。缺省構(gòu)造方法將成員變量初始化為缺省值。一旦程序員提供了自己的構(gòu)造方法,Java則不會再提供缺省構(gòu)造方法。重載構(gòu)造方法提供了一組創(chuàng)建對象的方式,可以根據(jù)需要決定是否帶初始參數(shù)。publicclassconstructOverload{intx,y;constructOverload(){x=0;

System.out.println("不帶參數(shù)的構(gòu)造方法");}

constructOverload(intx){this.x=x;System.out.println("帶一個參數(shù)的構(gòu)造方法");}

constructOverload(intx,inty){this(x);this.y=y;System.out.println(“兩個參數(shù)的構(gòu)造方法”);}}getter方法和setter方法設(shè)計

Java語言針對被私有化的成員變量可以提供訪問的方法:getter方法用來讀取對象成員變量的值setter方法用來修改對象成員變量的值我們正是通過提供一系列的get方法和set方法去讀寫這些對象內(nèi)部的成員數(shù)據(jù),在這些方法中我們可以過濾傳進來的參數(shù),就像人的消化系統(tǒng)一樣,所有的食物經(jīng)過消化系統(tǒng)后變成了對人有用的營養(yǎng),而非法數(shù)據(jù)則被過濾,這就是對象對外提供的交換接口。例如:publicStringgetName(){returnname;}publicvoidsetName(Stringn){name=n;}publicchargetSex(){returnsex;}publicvoidsetSex(chars){sex=(s=='F')?s:'M';}用getter方法保護敏感數(shù)據(jù)不會泄露,用setter方法過濾非法輸入數(shù)據(jù)!equals()方法&hashcode()方法用于比較兩個對象是否相等,相等返回trueObject類中提供的equals方法使用恒等函數(shù)來確定對象是否相等即只能用來判斷兩個不同的對象是否指向同一個內(nèi)存區(qū)域。子類一般通過修改Object的equals方法實現(xiàn)有意義的測試,可以實現(xiàn):若同一類型的兩個不同對象包含相同的信息即返回true。通用的equals方法的標(biāo)準(zhǔn)寫法建議如下例所示。publicbooleanequals(Objectobj){ if(this==obj) returntrue; if(obj==null) returnfalse; if(getClass()!=obj.getClass()) returnfalse; Complex1other=(Complex1)obj; if(imaginarypart!=other.imaginarypart||realpart!=other.realpart)returnfalse; returntrue;}Complex1one=newComplex1(3.0,4.0);Complex1anotherOne=newComplex1(3.0,4.0);if(one.equals(anotherOne))System.out.println("對象內(nèi)容相等");if(one==anotherOne)System.out.println(“它們指向同一個對象!”);//理解equals方法和==相等比較的不同。hashcode()methodisusedtoproducedahashcodewhichassociatedwithanobject.HashcodesShouldbescrambled----ifxandyaretwodistinctobjects,thereshouldbeahighprobabilitythatx.hashcode()andy.hashcode()aredifferent.publicinthashCode(){ finalintprime=31; intresult=1; longtemp; temp=Double.doubleToLongBits(imaginarypart); result=prime*result+(int)(temp^(temp>>>32)); temp=Double.doubleToLongBits(realpart); result=prime*result+(int)(temp^(temp>>>32)); returnresult;}toString()方法toString方法用于返回對象的字符串表示。Object類中的實現(xiàn)非常簡單,直接返回對象的引用,建議所有的子類都應(yīng)給出此方法。使用“+”運算符將對象同一個字符串連接,Java編譯器會自動調(diào)用toString方法,獲取對象的字符串表現(xiàn)形式。publicStringtoString(){Stringstr=""+realpart;if(imaginarypart<0.0)str=str+imaginarypart+"i";elsestr=str+"+"+imaginarypart+"i";returnstr;}Complex2m1=newComplex2(4.4,-8.9);System.out.println("m1="+m1);自動調(diào)用toString方法,獲取對象的字符串表示形式其他功能方法設(shè)計在類的設(shè)計中,除了針對封裝屬性提供的接口和重寫從父類中繼承的方法外,每一個類都應(yīng)該有自己獨特的功能方法,如針對【例3-4】中復(fù)數(shù)類給出的加減等方法,【例3-6】中學(xué)生類,可以添加求總分以及輸入數(shù)據(jù)等方法。publicdoubletotal(){doublesum=0.0;for(inti=0;i<coursescores.length;i++){sum+=coursescores[i];}returnsum;}publicvoidinputData(){Scannerin=newScanner(System.in);System.out.println("請輸入"+name+"的成績:");for(inti=0;i<coursescores.length;i++){System.out.print(coursenames[i]+":");coursescores[i]=in.nextDouble();}}抽象和封裝舉例假如我們現(xiàn)在要做一個班級成績管理系統(tǒng),首先應(yīng)該能輸入和保存一個班級的信息以及學(xué)生的相關(guān)信息,如何抽象、如何封裝?一種方案如下:1、抽象學(xué)生類:Student2、抽象班級類:Myclass3、測試學(xué)生類4、測試班級類5、主控程序類面向?qū)ο蟪绦蛟O(shè)計的基本原理從前面章節(jié)的知識和程序語言發(fā)展的歷史來研究面向?qū)ο蟪绦蛟O(shè)計理論,所謂面向?qū)ο笃鋵嵕褪窃诔绦蛟O(shè)計的發(fā)展歷史中逐漸形成的一套設(shè)計理論,并且還在繼續(xù)完善中。就當(dāng)下來看,整個面向?qū)ο蟪绦蛟O(shè)計理論主要建立在以下幾條原理之上:l抽象原理l封裝原理l繼承原理l多態(tài)原理l組合原理抽象原理抽象就是從大量的普遍的個體中抽象出共有的屬性和行為,從而形成一般化概念的過程。在現(xiàn)實世界中,人們正是通過抽象來理解復(fù)雜的事物。例如,人們并沒有把汽車當(dāng)作成百上千的零件組成來認(rèn)識,而是把它當(dāng)作具有自己特定行為的對象。我們可以忽略發(fā)動機、液壓傳輸、剎車系統(tǒng)等如何工作的細(xì)節(jié),而習(xí)慣于把汽車當(dāng)作一個整體來認(rèn)識。如果從一個抽象模型中剔除足夠多的細(xì)節(jié),則它將變得足夠通用,足以適應(yīng)于多種情況或場合,這樣的抽象常常在程序設(shè)計中非常有用。經(jīng)過對大量事物的抽象和歸類,可以形成相應(yīng)的類屬層次,如下圖就是一個自然界各事物的一個分類抽象:抽象原理下面我們通過一個示例來展示抽象原理,假設(shè)我們要在屏幕上用“*”打印矩形,可以把此矩形看成一個對象,用面向?qū)ο蟮乃季S來進行分析和抽象,所有的矩形都有寬(w)和高(h),并且在屏幕上有一個位置,而位置是由形如(x、y)的坐標(biāo)標(biāo)識出來的,所以最簡單的抽象就是通過(w、h、x、y)來定義一個矩形類(Rectangle),然后提供一個printme()方法在屏幕上打印出這個矩形。類圖如圖3-2所示,參考Java代碼示例如下:圖3-2Rectangle類publicclassRectangle{intx,y,w,h;Rectangle(){this(0,0,1,1);}publicRectangle(intx,inty,intw,inth){ this.x=x; this.y=y; this.w=w; this.h=h;}publicvoidprintme(Screenmyscreen){ myscreen.setY(y);for(inti=1;i<=h;i++){ myscreen.setX(x); myscreen.repeat('*',w);myscreen.println();}}}同樣的需要抽象“屏幕”類封裝原理封裝原理是一個普適性原理,正如我們看到的、我們學(xué)習(xí)到的、以及我們周圍的一切實體,包括動物、植物、各種人造物品都是封裝的,一般情況下,我們只能看到這些物體的“外殼”,看不到其內(nèi)部結(jié)構(gòu)。這種將內(nèi)部結(jié)構(gòu)和功能對外隱藏,只留下必需的接口和外界進行能量或信息交流就是封裝,比如說我們?nèi)祟悾覀兊膬?nèi)臟、血管、神經(jīng)都被封裝在我們皮膚里面,對外表現(xiàn)出來的僅僅是皮膚和五官接口,也就是說我們都是內(nèi)聚性很強的對象個體,但我們又留有眼耳鼻口等接口,我們通過這些接口在這個世間生存和忙碌。在面向?qū)ο蟪绦蛟O(shè)計中,我們應(yīng)該遵循同樣的原理,將對象的內(nèi)部結(jié)構(gòu)對外作信息隱藏,讓外部不可訪問,但提供一系列的公有接口,用來進行信息和能量交換。在java語言中,實現(xiàn)封裝的關(guān)鍵字是private,提供接口的關(guān)鍵字是public,如圖3-4所示。圖3-4封裝示意圖前面抽象了屏幕類(Screen),矩形類(Rectangle),并且用一個測試程序完成了測試。但有個問題,如果我們在測試程序中,直接修改矩形對象的內(nèi)部數(shù)據(jù),就會造成數(shù)據(jù)混亂,這些矩形對象已經(jīng)不是原來的矩形對象了,因為沒有封裝這是很難避免的,參考【例3-11】。如何防止數(shù)據(jù)被非法修改,這就需要使用封裝技術(shù)。在Java語言中,實現(xiàn)封裝的關(guān)鍵字是private,提供公有接口的關(guān)鍵字是public。實現(xiàn)封裝需要兩步,第一步,將對象內(nèi)部的屬性數(shù)據(jù)用private修飾,這樣其他對象就無法直接訪問和修改了,并且有些屬性在對象創(chuàng)建后再不允許修改,則此類屬性應(yīng)該定義為常量;第二步,對于需要訪問的屬性提供讀值方法getter,并需要特定代碼對數(shù)據(jù)進行處理,根據(jù)安全需要可隱藏某些數(shù)據(jù);對于需要修改的屬性提供寫值方法setter,并且在方法中提供約束和過濾代碼,保證合法數(shù)據(jù)進入,阻擋非法數(shù)據(jù)進入。實現(xiàn)封裝后屏幕類的代碼如下,參考【3示例-13】:封裝原理public

classScreen{private

final

intSCREEN_WIDTH;private

final

intSCREEN_HEIGHT;private

intx;private

inty;private

char[][]data;public

intgetX(){

returnx;}public

voidsetX(intx){

if(x<SCREEN_WIDTH)this.x=x;}public

intgetY(){

returny;}public

voidsetY(inty){

if(y<SCREEN_HEIGHT)this.y=y;}publicScreen(){ SCREEN_HEIGHT=50; SCREEN_WIDTH=80; data=newchar[SCREEN_HEIGHT][SCREEN_WIDTH];}publicScreen(intr,intc){//通過判斷對輸入的數(shù)據(jù)進行過濾 if(r>=1&&r<=1000) SCREEN_HEIGHT=r; else SCREEN_HEIGHT=50; if(c>=1&&c<=1000) SCREEN_WIDTH=c; else SCREEN_WIDTH=80; data=newchar[SCREEN_HEIGHT][SCREEN_WIDTH];}publicvoidinit(){ for(inti=0;i<SCREEN_HEIGHT;i++){ for(intj=0;j<SCREEN_WIDTH;j++){ data[i][j]=''; } }}。。。繼承原理繼承原理也是一個普適原理,如果沒有繼承,我們的生物世界就會永遠(yuǎn)在生物鏈的底端徘徊,就不會出現(xiàn)如此豐富的生態(tài)世界。繼承是發(fā)展的一部分,只有不斷地繼承舊的、成熟的東西,才能發(fā)展出更新的、更先進的東西,否則,我們就會在原地踏步,永遠(yuǎn)重復(fù)。在面向?qū)ο蟪绦蛟O(shè)計中,我們從已經(jīng)存在的類產(chǎn)生新類的機制,我們也稱之為繼承,原來存在的類叫父類(或叫基類),新類叫子類(或叫派生類)。子類中會自動擁有父類中的設(shè)計代碼,繼承帶來的好處是:一方面可減少程序設(shè)計的錯誤,另一方面,做到了代碼復(fù)用,可簡化和加快程序設(shè)計,提高了工作效率。繼承不僅僅是簡單的擁有父類的設(shè)計代碼,繼承機制本身就具有進化的能力,跟生物世界一樣,子代總是比父代更能適應(yīng)環(huán)境。我們通過對父類的設(shè)計作一些局部的修改,使得子類對象具有更好的適應(yīng)能力和強大的生存能力。publicclassTestInherit{publicstaticvoidmain(String[]args){Screenmyscreen=newScreen(25,80);myscreen.cls();Lingxingmylx=newLingxing(0,0,9);mylx.printme(myscreen);Lingxingmylx2=newLingxing(20,1,12);mylx2.printme(myscreen);Rectanglerc=newRectangle(14,1,5,7);rc.printme(myscreen);Triangletr=newTriangle(56,2,7);tr.printme(myscreen);Circlec=newCircle(34,0,10);c.printme(myscreen);myscreen.display(); }}繼承原理從教材【3-14】例可以看出,Shape類是各種圖形的抽象父類,從而可以派生出各種具體的圖形類,如Rectangle、Triangle等,子類自動擁有父類中的成員變量x,y,同時繼承下來了父類中的各種公有成員方法,各子類有根據(jù)自己形狀的特點,給出了printme()方法的覆蓋實現(xiàn),從而為實現(xiàn)多態(tài)打好了基礎(chǔ)。繼承提供的是is-a關(guān)系,即父類相對于子類更為抽象,子類更為具體,子類對象同樣隸屬父類型。TestInherit類中對以上各種子類進行了測試,測試結(jié)果如圖所示:多態(tài)原理多態(tài)性原理是生物多樣性在面向?qū)ο蟪绦蛟O(shè)計中的應(yīng)用,正如第一章我們說過的一樣,面對同樣的刺激、消息等,不同的動物的反應(yīng)是不一樣的。在面向?qū)ο蟪绦蛟O(shè)計中,如果我們有許多不同的對象,每個對象都具有相應(yīng)的行為模式(即執(zhí)行代碼),通過對每個對象發(fā)送同樣的消息,但每個對象的執(zhí)行的代碼是不一樣的,這就是面向?qū)ο蟪绦蛟O(shè)計中的多態(tài)。多態(tài)性(polymorphism)是面向?qū)ο缶幊痰幕A(chǔ)屬性,它允許多個方法使用同一個接口,從而導(dǎo)致在不同的上下文中,對象的執(zhí)行代碼可以不一樣。Java從多個方面支持多態(tài)性,其中兩個方面最為突出。第一個是每個方法都可以被子類重寫;第二個是設(shè)立interface關(guān)鍵字。鳥蛇魚人馬螞蟻move鳥蛇魚人馬螞蟻A地區(qū)B地區(qū)多態(tài)原理由于超類(父類)中的方法可以在派生類(子類)中重寫,因此創(chuàng)建類的層次結(jié)構(gòu)非常重要。在類的層次結(jié)構(gòu)中,每個子類都是它的父類的特化(specialization)或具體化。從類屬關(guān)系上來講,屬于底層類的對象肯定屬于高層類,例如,小學(xué)生類是學(xué)生類的子類,學(xué)生類是人類的子類等等,如果張三是一個小學(xué)生,則張三一定是一個學(xué)生,并且張三一定是一個人類。在Java中父類的引用可以指向子孫類對象,從而可以通過父類引用來調(diào)用子類對象的方法。在Java中,多態(tài)是通過動態(tài)綁定來實現(xiàn)的,通過父類的引用調(diào)用某子類對象的一個方法時,會自動執(zhí)行由該子類重寫后的版本。publicclassTestPolymorphism{publicstaticvoidmain(String[]args){Screenmyscreen=newScreen(25,80);myscreen.cls();Shapeshapes[]=newShape[5];//通過父類定義了有5個引用變量的數(shù)組shapes[0]=newLingxing(0,0,9);//指向一個菱形對象shapes[1]=newLingxing(20,1,12);shapes[2]=newRectangle(14,1,5,7);//指向一個矩形對象

shapes[3]=newTriangle(56,2,7);//指向一個三角形對象shapes[4]=newCircle(34,0,10);//指向一個圓形對象for(inti=0;i<shapes.length;i++){shapes[i].printme(myscreen);//方法調(diào)用相同,但因?qū)ο蟛煌瑘?zhí)行代碼也不同,這就是多態(tài)性原理}myscreen.display();}}組合原理在現(xiàn)實世界中我們常會看到一個復(fù)雜對象總是有許多子對象構(gòu)造而成,如汽車對象包含了發(fā)動機對象、輪胎對象、方向盤對象等,一個寵物狗對象也會包含心、肝、脾、肺等等。在面向?qū)ο蟪绦蛟O(shè)計中我們常用組合來完成從簡單對象到復(fù)雜對象的構(gòu)造過程,一個復(fù)雜對象常常是有多個簡單的成員對象組合而成,比如一個汽車對象由“發(fā)動機”、“剎車”、“方向盤”等對象組裝而成。相對于繼承的is-a關(guān)系,我們常說組合是has-a關(guān)系,即整體和部分的關(guān)系。使用組合的原因是通過組合可以降低構(gòu)建系統(tǒng)的復(fù)雜性,這也是人們解決復(fù)雜問題的通用方式。組合通常有兩種方式:聯(lián)合和聚合。

這些方式代表了對象之間不同的協(xié)作關(guān)系。任何組合類型都是has-a關(guān)系。然而,聯(lián)合和聚合的微小區(qū)別在于部分如何構(gòu)成整體。在聚合中,通常只看到整體,如手機或電視機,而在聯(lián)合中,通常看到的是組成整體的部分,如電腦、打印機、鼠標(biāo)、鍵盤構(gòu)成的辦公系統(tǒng),音響、功放、麥克風(fēng)、DVD播放機、電視機等構(gòu)成的家庭音響和影院系統(tǒng)等。在Java語言和.NET框架中組合概念更加重要。因為對象可以被動態(tài)加載,所以解耦設(shè)計很重要。例如,如果你發(fā)布了一個應(yīng)用程序,后來由于修復(fù)缺陷或者維護的目的,需要重新創(chuàng)建其中一個類文件,那么只需用重新發(fā)布這個特定的類文件即可。如果所有的代碼都在單個文件中,則需要重新發(fā)布整個應(yīng)用程序。聚合及其實現(xiàn)技術(shù)組合最直觀的方式就是聚合,聚合意味著一個復(fù)雜的對象由許多小對象構(gòu)成。比如我們每天使用的智能手機,外表看就是一個整體對象,但實際上它是由許多小部件組合而成。簡單的講,聚合往往是一個整體的封裝對象,對象內(nèi)部又可以分解為許多的標(biāo)準(zhǔn)小部件,每個小對象又都是具有特定功能和標(biāo)準(zhǔn)接口的封裝體,參考【例3-16】程序。publicclassComputer{//抽象的聚合后的簡易計算機privateCPUcpu;//組合子對象cpu處理計算privateMemorymemory;//組合子對象memory處理存儲privateKeyboardkeyboard;//組合子對象keyboard處理輸入privateScreenscreen;//組合子對象screen處理輸出publicComputer(){ memory=newMemory(); cpu=newCPU(memory); keyboard=newKeyboard(); screen=newScreen();} publicComputer(CPUcpu,Memorymemory,Keyboardkeyboard,Screenscreen){ super(); this.cpu=cpu; this.memory=memory; this.keyboard=keyboard; this.screen=screen; }}publicvoiddoWork(){//模擬計算機開機工作方法screen.print("第一個操作數(shù):");memory.setFirstnum(keyboard.inputDouble());screen.print("運算符:");cpu.setInstruct(keyboard.inputString());screen.print("第二個操作數(shù):");memory.setSecondnum(keyboard.inputDouble());cpu.calculate();screen.println("計算結(jié)果:"+memory.getResult());}publicclassTestComputer{publicstaticvoidmain(String[]args){ Computermycomputer=newComputer();//創(chuàng)建一個Computer對象 mycomputer.doWork();//執(zhí)行計算任務(wù)}}聯(lián)合及其實現(xiàn)技術(shù)聯(lián)合代表若干獨立的對象可以連接而成一個更復(fù)雜和功能更強大的對象。比如在家庭影院系統(tǒng),電視機、音響、DVD播放機等各種各樣的組件都是獨立的,都可以提供特定的功能,但我們通過一些插接線連接后構(gòu)成了一個功能更強大系統(tǒng)。同樣的,計算機、打印機、麥克風(fēng)、音響、攝像頭等也都是獨立存在的小對象,我們將它們連接在一起就會形成功能更豐富、效率更高的復(fù)雜對象。簡單理解,聯(lián)合是將若干獨立的子對象連接起來形成具有復(fù)雜功能的更大對象,如下面的示例,我們抽象了打印機、攝像頭、音箱、麥克風(fēng)等小對象,通過聯(lián)合可完成更復(fù)雜的功能,參考【例3-17】程序。publicclassTestUnion{publicstaticvoidmain(String[]args){ Computer1mycomputer=newComputer1("聯(lián)系昭陽450電腦"); Printermyprinter=newPrinter("BrotherDCP-7057打印機"); Cameramycamera=newCamera("奧尼劍影攝像頭"); SoundBoxmysound=newSoundBox("好牧人V8音箱"); Microphonemymc=newMicrophone("飛利浦麥克風(fēng)"); mycomputer.playMusic(mys

溫馨提示

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

最新文檔

評論

0/150

提交評論