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

下載本文檔

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

文檔簡(jiǎn)介

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

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

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

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

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

25a3000inta=25;

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

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

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

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

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

引用本身按值傳遞Date2002,5,30Date2003,7,23obj1obj2調(diào)用swapobj(obj1,obj2)可改變對(duì)象狀態(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)造方法對(duì)象是類實(shí)例化后的產(chǎn)物,所謂實(shí)例化是按照類的設(shè)計(jì)創(chuàng)造對(duì)象的過程,就是給此對(duì)象分配內(nèi)存空間并初始化,即要進(jìn)行一系列的構(gòu)造工作,使其變成一個(gè)合適的、可用的對(duì)象,這就是構(gòu)造方法所完成的工作,類似于現(xiàn)實(shí)世界中動(dòng)物對(duì)象的分娩或孵化過程。l構(gòu)造方法是類中一個(gè)特殊的方法,特殊之處在于此方法第一要與類名同名,第二方法不能有返回類型。l構(gòu)造方法不能有返回類型并不能代表它不能有返回值,實(shí)際上它要返回對(duì)象在內(nèi)存中的開始地址。l構(gòu)造方法可以重載,并且我們把沒有任何參數(shù)的構(gòu)造方法稱為默認(rèn)構(gòu)造方法。如前例中的Complex()是默認(rèn)構(gòu)造方法,而Complex(doubles,doublex)則是帶有兩個(gè)形參的構(gòu)造方法。創(chuàng)建對(duì)象使用下列語法可創(chuàng)建對(duì)象:

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

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

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

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

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

Java語言針對(duì)被私有化的成員變量可以提供訪問的方法:getter方法用來讀取對(duì)象成員變量的值setter方法用來修改對(duì)象成員變量的值我們正是通過提供一系列的get方法和set方法去讀寫這些對(duì)象內(nèi)部的成員數(shù)據(jù),在這些方法中我們可以過濾傳進(jìn)來的參數(shù),就像人的消化系統(tǒng)一樣,所有的食物經(jīng)過消化系統(tǒng)后變成了對(duì)人有用的營養(yǎng),而非法數(shù)據(jù)則被過濾,這就是對(duì)象對(duì)外提供的交換接口。例如:publicStringgetName(){returnname;}publicvoidsetName(Stringn){name=n;}publicchargetSex(){returnsex;}publicvoidsetSex(chars){sex=(s=='F')?s:'M';}用getter方法保護(hù)敏感數(shù)據(jù)不會(huì)泄露,用setter方法過濾非法輸入數(shù)據(jù)!equals()方法&hashcode()方法用于比較兩個(gè)對(duì)象是否相等,相等返回trueObject類中提供的equals方法使用恒等函數(shù)來確定對(duì)象是否相等即只能用來判斷兩個(gè)不同的對(duì)象是否指向同一個(gè)內(nèi)存區(qū)域。子類一般通過修改Object的equals方法實(shí)現(xiàn)有意義的測(cè)試,可以實(shí)現(xiàn):若同一類型的兩個(gè)不同對(duì)象包含相同的信息即返回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("對(duì)象內(nèi)容相等");if(one==anotherOne)System.out.println(“它們指向同一個(gè)對(duì)象!”);//理解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方法用于返回對(duì)象的字符串表示。Object類中的實(shí)現(xiàn)非常簡(jiǎn)單,直接返回對(duì)象的引用,建議所有的子類都應(yīng)給出此方法。使用“+”運(yùn)算符將對(duì)象同一個(gè)字符串連接,Java編譯器會(huì)自動(dòng)調(diào)用toString方法,獲取對(duì)象的字符串表現(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);自動(dòng)調(diào)用toString方法,獲取對(duì)象的字符串表示形式其他功能方法設(shè)計(jì)在類的設(shè)計(jì)中,除了針對(duì)封裝屬性提供的接口和重寫從父類中繼承的方法外,每一個(gè)類都應(yīng)該有自己獨(dú)特的功能方法,如針對(duì)【例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("請(qǐng)輸入"+name+"的成績(jī):");for(inti=0;i<coursescores.length;i++){System.out.print(coursenames[i]+":");coursescores[i]=in.nextDouble();}}抽象和封裝舉例假如我們現(xiàn)在要做一個(gè)班級(jí)成績(jī)管理系統(tǒng),首先應(yīng)該能輸入和保存一個(gè)班級(jí)的信息以及學(xué)生的相關(guān)信息,如何抽象、如何封裝?一種方案如下:1、抽象學(xué)生類:Student2、抽象班級(jí)類:Myclass3、測(cè)試學(xué)生類4、測(cè)試班級(jí)類5、主控程序類面向?qū)ο蟪绦蛟O(shè)計(jì)的基本原理從前面章節(jié)的知識(shí)和程序語言發(fā)展的歷史來研究面向?qū)ο蟪绦蛟O(shè)計(jì)理論,所謂面向?qū)ο笃鋵?shí)就是在程序設(shè)計(jì)的發(fā)展歷史中逐漸形成的一套設(shè)計(jì)理論,并且還在繼續(xù)完善中。就當(dāng)下來看,整個(gè)面向?qū)ο蟪绦蛟O(shè)計(jì)理論主要建立在以下幾條原理之上:l抽象原理l封裝原理l繼承原理l多態(tài)原理l組合原理抽象原理抽象就是從大量的普遍的個(gè)體中抽象出共有的屬性和行為,從而形成一般化概念的過程。在現(xiàn)實(shí)世界中,人們正是通過抽象來理解復(fù)雜的事物。例如,人們并沒有把汽車當(dāng)作成百上千的零件組成來認(rèn)識(shí),而是把它當(dāng)作具有自己特定行為的對(duì)象。我們可以忽略發(fā)動(dòng)機(jī)、液壓傳輸、剎車系統(tǒng)等如何工作的細(xì)節(jié),而習(xí)慣于把汽車當(dāng)作一個(gè)整體來認(rèn)識(shí)。如果從一個(gè)抽象模型中剔除足夠多的細(xì)節(jié),則它將變得足夠通用,足以適應(yīng)于多種情況或場(chǎng)合,這樣的抽象常常在程序設(shè)計(jì)中非常有用。經(jīng)過對(duì)大量事物的抽象和歸類,可以形成相應(yīng)的類屬層次,如下圖就是一個(gè)自然界各事物的一個(gè)分類抽象:抽象原理下面我們通過一個(gè)示例來展示抽象原理,假設(shè)我們要在屏幕上用“*”打印矩形,可以把此矩形看成一個(gè)對(duì)象,用面向?qū)ο蟮乃季S來進(jìn)行分析和抽象,所有的矩形都有寬(w)和高(h),并且在屏幕上有一個(gè)位置,而位置是由形如(x、y)的坐標(biāo)標(biāo)識(shí)出來的,所以最簡(jiǎn)單的抽象就是通過(w、h、x、y)來定義一個(gè)矩形類(Rectangle),然后提供一個(gè)printme()方法在屏幕上打印出這個(gè)矩形。類圖如圖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();}}}同樣的需要抽象“屏幕”類封裝原理封裝原理是一個(gè)普適性原理,正如我們看到的、我們學(xué)習(xí)到的、以及我們周圍的一切實(shí)體,包括動(dòng)物、植物、各種人造物品都是封裝的,一般情況下,我們只能看到這些物體的“外殼”,看不到其內(nèi)部結(jié)構(gòu)。這種將內(nèi)部結(jié)構(gòu)和功能對(duì)外隱藏,只留下必需的接口和外界進(jìn)行能量或信息交流就是封裝,比如說我們?nèi)祟悾覀兊膬?nèi)臟、血管、神經(jīng)都被封裝在我們皮膚里面,對(duì)外表現(xiàn)出來的僅僅是皮膚和五官接口,也就是說我們都是內(nèi)聚性很強(qiáng)的對(duì)象個(gè)體,但我們又留有眼耳鼻口等接口,我們通過這些接口在這個(gè)世間生存和忙碌。在面向?qū)ο蟪绦蛟O(shè)計(jì)中,我們應(yīng)該遵循同樣的原理,將對(duì)象的內(nèi)部結(jié)構(gòu)對(duì)外作信息隱藏,讓外部不可訪問,但提供一系列的公有接口,用來進(jìn)行信息和能量交換。在java語言中,實(shí)現(xiàn)封裝的關(guān)鍵字是private,提供接口的關(guān)鍵字是public,如圖3-4所示。圖3-4封裝示意圖前面抽象了屏幕類(Screen),矩形類(Rectangle),并且用一個(gè)測(cè)試程序完成了測(cè)試。但有個(gè)問題,如果我們?cè)跍y(cè)試程序中,直接修改矩形對(duì)象的內(nèi)部數(shù)據(jù),就會(huì)造成數(shù)據(jù)混亂,這些矩形對(duì)象已經(jīng)不是原來的矩形對(duì)象了,因?yàn)闆]有封裝這是很難避免的,參考【例3-11】。如何防止數(shù)據(jù)被非法修改,這就需要使用封裝技術(shù)。在Java語言中,實(shí)現(xiàn)封裝的關(guān)鍵字是private,提供公有接口的關(guān)鍵字是public。實(shí)現(xiàn)封裝需要兩步,第一步,將對(duì)象內(nèi)部的屬性數(shù)據(jù)用private修飾,這樣其他對(duì)象就無法直接訪問和修改了,并且有些屬性在對(duì)象創(chuàng)建后再不允許修改,則此類屬性應(yīng)該定義為常量;第二步,對(duì)于需要訪問的屬性提供讀值方法getter,并需要特定代碼對(duì)數(shù)據(jù)進(jìn)行處理,根據(jù)安全需要可隱藏某些數(shù)據(jù);對(duì)于需要修改的屬性提供寫值方法setter,并且在方法中提供約束和過濾代碼,保證合法數(shù)據(jù)進(jìn)入,阻擋非法數(shù)據(jù)進(jìn)入。實(shí)現(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){//通過判斷對(duì)輸入的數(shù)據(jù)進(jìn)行過濾 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]=''; } }}。。。繼承原理繼承原理也是一個(gè)普適原理,如果沒有繼承,我們的生物世界就會(huì)永遠(yuǎn)在生物鏈的底端徘徊,就不會(huì)出現(xiàn)如此豐富的生態(tài)世界。繼承是發(fā)展的一部分,只有不斷地繼承舊的、成熟的東西,才能發(fā)展出更新的、更先進(jìn)的東西,否則,我們就會(huì)在原地踏步,永遠(yuǎn)重復(fù)。在面向?qū)ο蟪绦蛟O(shè)計(jì)中,我們從已經(jīng)存在的類產(chǎn)生新類的機(jī)制,我們也稱之為繼承,原來存在的類叫父類(或叫基類),新類叫子類(或叫派生類)。子類中會(huì)自動(dòng)擁有父類中的設(shè)計(jì)代碼,繼承帶來的好處是:一方面可減少程序設(shè)計(jì)的錯(cuò)誤,另一方面,做到了代碼復(fù)用,可簡(jiǎn)化和加快程序設(shè)計(jì),提高了工作效率。繼承不僅僅是簡(jiǎn)單的擁有父類的設(shè)計(jì)代碼,繼承機(jī)制本身就具有進(jìn)化的能力,跟生物世界一樣,子代總是比父代更能適應(yīng)環(huán)境。我們通過對(duì)父類的設(shè)計(jì)作一些局部的修改,使得子類對(duì)象具有更好的適應(yīng)能力和強(qiá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等,子類自動(dòng)擁有父類中的成員變量x,y,同時(shí)繼承下來了父類中的各種公有成員方法,各子類有根據(jù)自己形狀的特點(diǎn),給出了printme()方法的覆蓋實(shí)現(xiàn),從而為實(shí)現(xiàn)多態(tài)打好了基礎(chǔ)。繼承提供的是is-a關(guān)系,即父類相對(duì)于子類更為抽象,子類更為具體,子類對(duì)象同樣隸屬父類型。TestInherit類中對(duì)以上各種子類進(jìn)行了測(cè)試,測(cè)試結(jié)果如圖所示:多態(tài)原理多態(tài)性原理是生物多樣性在面向?qū)ο蟪绦蛟O(shè)計(jì)中的應(yīng)用,正如第一章我們說過的一樣,面對(duì)同樣的刺激、消息等,不同的動(dòng)物的反應(yīng)是不一樣的。在面向?qū)ο蟪绦蛟O(shè)計(jì)中,如果我們有許多不同的對(duì)象,每個(gè)對(duì)象都具有相應(yīng)的行為模式(即執(zhí)行代碼),通過對(duì)每個(gè)對(duì)象發(fā)送同樣的消息,但每個(gè)對(duì)象的執(zhí)行的代碼是不一樣的,這就是面向?qū)ο蟪绦蛟O(shè)計(jì)中的多態(tài)。多態(tài)性(polymorphism)是面向?qū)ο缶幊痰幕A(chǔ)屬性,它允許多個(gè)方法使用同一個(gè)接口,從而導(dǎo)致在不同的上下文中,對(duì)象的執(zhí)行代碼可以不一樣。Java從多個(gè)方面支持多態(tài)性,其中兩個(gè)方面最為突出。第一個(gè)是每個(gè)方法都可以被子類重寫;第二個(gè)是設(shè)立interface關(guān)鍵字。鳥蛇魚人馬螞蟻move鳥蛇魚人馬螞蟻A地區(qū)B地區(qū)多態(tài)原理由于超類(父類)中的方法可以在派生類(子類)中重寫,因此創(chuàng)建類的層次結(jié)構(gòu)非常重要。在類的層次結(jié)構(gòu)中,每個(gè)子類都是它的父類的特化(specialization)或具體化。從類屬關(guān)系上來講,屬于底層類的對(duì)象肯定屬于高層類,例如,小學(xué)生類是學(xué)生類的子類,學(xué)生類是人類的子類等等,如果張三是一個(gè)小學(xué)生,則張三一定是一個(gè)學(xué)生,并且張三一定是一個(gè)人類。在Java中父類的引用可以指向子孫類對(duì)象,從而可以通過父類引用來調(diào)用子類對(duì)象的方法。在Java中,多態(tài)是通過動(dòng)態(tài)綁定來實(shí)現(xiàn)的,通過父類的引用調(diào)用某子類對(duì)象的一個(gè)方法時(shí),會(huì)自動(dòng)執(zhí)行由該子類重寫后的版本。publicclassTestPolymorphism{publicstaticvoidmain(String[]args){Screenmyscreen=newScreen(25,80);myscreen.cls();Shapeshapes[]=newShape[5];//通過父類定義了有5個(gè)引用變量的數(shù)組shapes[0]=newLingxing(0,0,9);//指向一個(gè)菱形對(duì)象shapes[1]=newLingxing(20,1,12);shapes[2]=newRectangle(14,1,5,7);//指向一個(gè)矩形對(duì)象

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

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

溫馨提示

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

評(píng)論

0/150

提交評(píng)論