面向?qū)ο缶幊袒A(chǔ)_第1頁
面向?qū)ο缶幊袒A(chǔ)_第2頁
面向?qū)ο缶幊袒A(chǔ)_第3頁
面向?qū)ο缶幊袒A(chǔ)_第4頁
面向?qū)ο缶幊袒A(chǔ)_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第三章 面向?qū)ο缶幊袒A(chǔ)3.1 面向?qū)ο蟾拍钤谡嬲拿嫦驅(qū)ο笳Z言中,所有問題都是通過對象表示的,對象是面向?qū)ο蟪绦蛟O(shè)計的主要概念,它把有關(guān)的現(xiàn)實世界的實體模型化。對象是面向?qū)ο缶幊谭椒ǖ幕境煞?,每個對象都可用他本身的一組屬性和在其上的一組操作來定義。對象可以是現(xiàn)實生活中的一個物理對象,也可以是某一類概念實體的實例。任何事物都是一個對象,例如,一個人,一輛車、一本書、乃至一種語言、一個圖形、一種管理方式,都可作為一個對象。聲明實體的方法有:描述實體,包括實體的屬性和可執(zhí)行的操作。例如,對于汽車對象,它的顏色、重量都可以作為對象的屬性,它可以執(zhí)行的操作是行駛、鳴笛等。而面向?qū)ο蠓椒?,就是發(fā)送信息

2、給對象,通過發(fā)送信息實現(xiàn)對它的請求,而不管信息在其內(nèi)部如何存儲。面向?qū)ο缶幊痰闹饕瓌t之一就是封裝,封裝就是隱藏對象的內(nèi)部數(shù)據(jù)和方法,而只提供一個給外界訪問的接口。一個對象的內(nèi)部如何實現(xiàn)他的工作并不重要,只要該對象能進行工作即可。給對象提供一個接口,使用該接口使對象執(zhí)行一個給定的任務(wù)。因此,根據(jù)定義,一個對象不僅包含數(shù)據(jù),而且還包含在該數(shù)據(jù)上工作的方法。3.1.1 對象、類、實例化類是一種數(shù)據(jù)類型,它有與之相關(guān)的方法。一個對象就是一個類型或類的實例。最合適的定義:一個類就是一個對象的藍(lán)本。作為一個開發(fā)者來說,如同一個建筑工程師,創(chuàng)建一個藍(lán)本就是要創(chuàng)建一個房子的藍(lán)本,一旦藍(lán)本完成,則只要具有給定

3、任一房子形式的藍(lán)本即可。如此的表示,一個類就是一個給定功能集的藍(lán)本,而創(chuàng)建一個特定類的一個對象,他就具有所構(gòu)造類的所有功能。實例化是面向?qū)ο缶幊痰囊粋€獨特的術(shù)語。實例化是創(chuàng)建一個類的實例的行為,該實例是一個對象。形式為: 類名 對象名=new 類名(); 或 類名 對象名=new 類名(參數(shù)表);在實例化之后,可通過它的公有(public)成員與這個對象通信,如果沒有一個實際的對象,則不能做這一工作。但作為靜態(tài)成員時除外。當(dāng)每個對象都有同樣的能力時,每個實例將包含它自己的實例數(shù)據(jù),并能分別進行處理。3.1.2 面向?qū)ο蟪绦蛟O(shè)計語言的三大原則所有面向?qū)ο笳Z言都必須支持三個概念:對象、類和繼承,即

4、面向?qū)ο笳Z言都依賴于封裝、繼承和多態(tài)三個原則,而封裝和多態(tài)性則像類和繼承一樣,可完整的構(gòu)建面向?qū)ο蟮南到y(tǒng)。1、封裝封裝常常稱為信息隱藏。封裝能隱藏一個對象的本質(zhì)(內(nèi)部細(xì)節(jié)),使它與用戶分離開來,并只對用戶能直接操作的那些成員提供一個接口。封裝對一個類的外部接口(即對類的用戶,公有成員是可見的)和它的內(nèi)部實現(xiàn)細(xì)節(jié)之間提供邊界,封裝能使面臨一個類的成員仍然是靜態(tài)的或者不變的成員,而可隱藏更多的動態(tài)的和非永久性的類內(nèi)部細(xì)節(jié)。在C#中,封裝是依靠對每個類成員指定一個訪問修飾符(public、private、protected)來達(dá)到的。(1)抽象的設(shè)計。抽象表示程序中一個給定空間的問題,程序設(shè)計語言本

5、身提供了抽象。面向?qū)ο笳Z言允許我們聲明名字和接口更精確的模擬現(xiàn)實世界問題實體的類,以便使用對象能實現(xiàn)它們。應(yīng)該能為類的用戶提供最好的抽象設(shè)計,以使用戶不陷入到類工作的細(xì)節(jié)中。類的接口是抽象的實現(xiàn),例如自動售貨機,它內(nèi)部的情況是完全被封裝的,它必須有接受現(xiàn)金及用戶的選擇項,以實行交換,因此,自動售貨機必須具有一個向他的用戶表達(dá)功能的機構(gòu)-接口,即通過一個貨幣投切口及選擇所需項目的按鈕。雖然自動售貨機有許多種類,但主要是它的內(nèi)部結(jié)構(gòu)不同,基本接口則不需要有很多改變。為此,創(chuàng)建一個接口,由它提供給用戶訪問,并提供與類的內(nèi)部工作分離的信息與方法。(2)充分抽象的好處。類的抽象設(shè)計在開發(fā)可重用軟件方面是

6、很重要的,如果開發(fā)一個不變的、持續(xù)交叉實現(xiàn)改變的靜態(tài)接口,則只需要比較少的時間來修改應(yīng)用程序。用戶與實現(xiàn)細(xì)節(jié)分離。能使得一個完整的系統(tǒng)較容易理解,因而較容易維護。2、繼承(1)繼承的定義。繼承是指定一個類與另一個類具有一種關(guān)系。通過繼承,我們可以創(chuàng)建(或派生)一個基于已有類的新類。因而,可以修改所需的狀況和創(chuàng)建新的派生類的對象。這種能力是創(chuàng)建一個類層次的精華。在抽象的外部,繼承是一個系統(tǒng)的全部設(shè)計的最主要的部分,派生類是被創(chuàng)建的新類,而基類是派生新類的類。最近派生的類繼承了基類的所有成員,因而使得我們能夠重用以前的工作。(2)固有繼承的定義。固有繼承就是替換性,是指派生類通知的行為對基類來說是

7、可替換的。它的最主要的法則是掌握構(gòu)建層次。當(dāng)創(chuàng)建類層次時,一個派生類在任何繼承的接口上,不應(yīng)再要求并允許和它的基類一樣。當(dāng)擁有一個派生類的引用時,總是要把該類作為它的基類來處理,一個派生類可以添加更為限制有關(guān)它的要求的行為,并允許作為它需要的一小部分。3、多態(tài)性多態(tài)性具有老代碼調(diào)用新代碼的功能,它允許我們擴展或增強系統(tǒng)而又不修改或破壞已有的代碼。多態(tài)性有兩個好處:第一,它能聚集公用基類的對象,并始終如一的處理它們。由于多態(tài)性,當(dāng)我們調(diào)用這些對象的方法之一時,運行時能確保調(diào)用正確的派生對象的方法。第二,老代碼可以使用新代碼。多態(tài)性運行時能確保調(diào)用正確的派生類的成員,也可添加其他派生的類型到系統(tǒng),

8、所有代碼都繼續(xù)工作,而無需改變初始的代碼。3.2 類類是一個模板,它用來定義類的形態(tài)。類指定了對象的數(shù)據(jù)以及操作這些數(shù)據(jù)的代碼、C#用類的規(guī)范來構(gòu)造對象。對象是類的實例(inseances)。因此,一個類本質(zhì)上說是操作集,它指定了怎樣來創(chuàng)建一個對象。類是邏輯抽象的,清楚的認(rèn)識這一點是很重要的。只有創(chuàng)建了類的對象,類才物理的體現(xiàn)在內(nèi)存中。還有一點需要注意:構(gòu)成類的變量和方法都稱作該類的成員(members)。3.2.1 類的聲明為了舉例說明類,我們展開一個封裝了車輛信息-包括轎車、平板車和卡車的類。這個類叫做Vehicle,它存儲關(guān)于車輛的三個項目信息:它能夠運送的乘客數(shù)、它的燃料容量和它的平均

9、燃料消耗(每加侖英里數(shù))。Vehicle的第一個版本如下所示。它定義了三個實例變量:passengers,fuelcap和mpg。注意類并沒有包含任何方法。因此,目前他是一個僅含數(shù)據(jù)成員的類。class Vehicle public int passengers; /乘客數(shù) public int fuelcap; /所耗燃料 public int mpg; /每英里耗油量 Vehicle類中定義的實例變量說明了定義實例變量的一般形式。定義實例變量的一般形式如下所示: access type var-name;這里access指定訪問方式,type指定變量的類型,var-name是變量名。因此除

10、去訪問說明符,實例變量的定義方式與定義一個本地變量一樣。對于Vehicle類,變量是緊跟著訪問說明符public,這說明它們可以被Vehicle類以外的代碼訪問。定義一個類實際上是創(chuàng)建了一個新的數(shù)據(jù)類型。在本例中,這個新的數(shù)據(jù)類型是Vehicle。你可以用Vehicle來定義一個Vehicle類型的對象。記住類聲明僅僅只是類型描述,并沒有真正的創(chuàng)建對象。因此,前面的代碼并沒有使任何Vehicle類型的對象實際存在。要真正創(chuàng)建一個Vehicle對象,使用如下所示的語句:Vehicle minivan=new Vehicle();這條語句執(zhí)行后,Vehicle類的一個實例minivan,就“物理”

11、存在了。每當(dāng)創(chuàng)建類的一個實例,就創(chuàng)建了該類的一個對象,每個對象自身包含類中定義的所有實例變量的一個拷貝。因此,每一個Vehicle對象都有它自身的實例變量- passengers,fuelcap和mpg的拷貝。要訪問這些變量,你得使用點(.)運算符。點運算符連接對象名和它的成員名。使用點運算符的一般形式如下所示: object.member對象名在點運算符的左邊,成員名在右邊。例如,可以給minivan的fuelcap變量賦值16:Minivan.fuelcap=16;一般來說,可以使用點運算符來訪問實例變量和方法。例3-1 下面是使用Vehicle類的一個完整的程序:/* 一個使用Vehic

12、le類的程序 文件名:UseVehicle.cs */using System;class Vehicle public int passengers; /乘客數(shù) public int fuelcap; /所耗燃料 public int mpg; /每英里耗油量 /這個類聲明了類型Vehicle的一個對象class VehicleDemo public static void Main() Vehicle minivan=new Vehicle(); int range; /給minivan的各個域賦值 minivan.passengers=7; minivan.fuelcap=16; min

13、ivan.mpg=21; /計算一罐燃料所能行駛的距離 range=minivan.fuelcap*minivan.mpg; Console.WriteLine("Minivan can carry"+minivan.passengers+"with a range of"+range); Console.Read();結(jié)果如下: Minivan can carry 7 with a range of 336這個程序由兩個類組成:Vehicle和VehicleDemo。在VehicleDemo中,方法Main()創(chuàng)建了Vehicle的實例minivan。

14、接著Main()中的代碼訪問與minivan相聯(lián)系的實例變量,給它們賦值并使用這些值。理解Vehicle和VehicleDemo是兩個分離的類是很重要的。它們彼此之間的關(guān)系僅僅是一個類創(chuàng)建了另一個類的實例。盡管它們是分離的類,VehicleDemo中的代碼可以訪問Vehicle的成員,因為這些成員被聲明為public。如果它們沒有指定public訪問說明符,對他們的訪問將被限制在類Vehicle中,類VehicleDemo不能訪問它們。類的具體實現(xiàn)是通過class-body來實現(xiàn)的,在class-body中定義的所有元素都被統(tǒng)稱為類的成員,這些成員包括:構(gòu)造函數(shù) 初始化類的對象。析構(gòu)函數(shù) 回收

15、對象的資源。常量 代表一個常量。字段 和類相關(guān)的變量成員。屬性 描述類的屬性的成員。索引 提供對類的對象的下標(biāo)支持。事件 定義類響應(yīng)用戶的事件及其對應(yīng)的處理程序。操作符 和類相關(guān)的重載操作符。3.2.3 構(gòu)造函數(shù)和析構(gòu)函數(shù)構(gòu)造函數(shù)和析構(gòu)函數(shù)是類中比較特殊的兩種成員函數(shù)。它們主要負(fù)責(zé)對對象進行初始化和回收對象的資源。一般來說,對象的生命周期都是以構(gòu)造函數(shù)開始,以析構(gòu)函數(shù)結(jié)束。如果一個類含有構(gòu)造函數(shù),則在建立該類的對象時就要調(diào)用它;而如果一個類含有析構(gòu)函數(shù),則在銷毀該類的對象時調(diào)用它。構(gòu)造函數(shù)和它所在的類具有相同的名字,當(dāng)定義該類的對象時,構(gòu)造函數(shù)完成對此對象的初始化。析構(gòu)函數(shù)和構(gòu)造函數(shù)的名字相同

16、(也就是說和類名相同),但在函數(shù)名前加一個波浪號“”,當(dāng)退出含有該對象的程序時,析構(gòu)函數(shù)將自動釋放這個對象所占的內(nèi)存空間。1、 構(gòu)造函數(shù)在前面的例子中,每個Vehicle對象的實例變量都得使用下面的一系列語句來人工設(shè)置的:minivan.passengers=7; minivan.fuelcap=16; minivan.mpg=21;為了減少出錯的可能性(可能忘了給某個變量賦值),有一個簡單的更好的方式來完成同樣的任務(wù):構(gòu)造函數(shù)(constructor)。構(gòu)造函數(shù)是一個特殊的成員函數(shù),它主要用來為對象分配內(nèi)存空間,對類的數(shù)據(jù)成員進行初始化并執(zhí)行對象的其他內(nèi)部管理操作。構(gòu)造函數(shù)的名字和它所在的類

17、名相同,它可以接收參數(shù)并允許重載。當(dāng)一個類含有多個構(gòu)造函數(shù)時,編譯程序為了確定調(diào)用哪一個構(gòu)造函數(shù),需要把對象中使用的參數(shù)和構(gòu)造函數(shù)的參數(shù)表進行比較,這個過程與在普通的函數(shù)重載中進行選擇的過程是一樣的。一個構(gòu)造函數(shù)在對象創(chuàng)建的時候初始化該對象。它和類的名字一樣,語法上與方法類似。然而構(gòu)造函數(shù)沒有返回值。定義類的構(gòu)造函數(shù)的基本格式如下所示: attributes constructor-modifiers constructor-name :base(argument-listopt) :this(argument-listopt) constructor-declarator block 簡單的

18、可以寫成:class-name /構(gòu)造函數(shù)代碼 其中:attribute 用于指定構(gòu)造函數(shù)的特征,它和類的attributes類似。constructor-modifiers 用于指定構(gòu)造函數(shù)的訪問范圍。base 用于調(diào)用基類的構(gòu)造函數(shù)。this 和base對應(yīng),主要用于調(diào)用當(dāng)前對象的構(gòu)造函數(shù)。constructor-declarator block 用于指定構(gòu)造函數(shù)的具體實現(xiàn)。典型的,你可以使用構(gòu)造函數(shù)給類中所定義的實例變量賦一個初值,或者執(zhí)行一些在創(chuàng)建對象時就必須執(zhí)行的初始化操作。無論是否定義,所有的類都有構(gòu)造函數(shù),因為C#自動提供一個缺省的構(gòu)造函數(shù)來把類中定義的實例變量初始化為0(對于值

19、類型)或null(對于引用類型)。但是,一旦你定義了自己的構(gòu)造函數(shù),缺省的構(gòu)造函數(shù)就不再使用。例3-2 下面是一個使用構(gòu)造函數(shù)的簡單例子。/一個簡單的構(gòu)造函數(shù)using System;class MyClass public int x; public MyClass() /類MyClass的構(gòu)造函數(shù) x=10; class Demo public static void Main() MyClass t1 = new MyClass(); MyClass t2 = new MyClass(); Console.WriteLine(t1.x+" "+t2.x); Conso

20、le.Read(); 結(jié)果為: 10 10在這個例子中,MyClass的構(gòu)造函數(shù)是:public MyClass() /類MyClass的構(gòu)造函數(shù) x=10; 注意,構(gòu)造函數(shù)被指定為public。這是因為構(gòu)造函數(shù)要被定義在類外的代碼調(diào)用。上面的構(gòu)造函數(shù)給MyClass類的實例變量x賦初值為10.當(dāng)一個對象被創(chuàng)建時,該構(gòu)造函數(shù)被new調(diào)用。例如,在下面的代碼中: MyClass t1 = new MyClass();構(gòu)造函數(shù)MyClass()在對象t1上被調(diào)用,給t1.x賦值為10.對象t2也一樣,當(dāng)其被構(gòu)造后,t2.x的值也是10。在上面的例子中,使用的是不含參數(shù)的構(gòu)造函數(shù)。雖然在某些情況下這

21、很好,但是更普遍的是你需要構(gòu)造函數(shù)接收一個或多個參數(shù)。給構(gòu)造函數(shù)增加參數(shù)與給方法增加參數(shù)一樣:在構(gòu)造函數(shù)名的括號中聲明它們。例3-3 給MyClass類增加一個帶參數(shù)的構(gòu)造函數(shù)/帶參數(shù)的構(gòu)造函數(shù)using System;class MyClass public int x; public MyClass(int i) x=i; class PramConsDemo public static void Main() MyClass t1 = new MyClass(10); MyClass t2 = new MyClass(88); Console.WriteLine(t1.x+"

22、"+t2.x); Console.Read(); 結(jié)果為:10 88在這個版本的程序中,構(gòu)造函數(shù)MyClass()定義了一個參數(shù)i,它用來初始化實例變量x。因此,當(dāng)MyClass t1 = new MyClass(10);執(zhí)行時,10被傳給i,接著把它賦給變量x。例3-4 改進類Vehicle:添加一個構(gòu)造函數(shù),使得在構(gòu)造一個對象時自動初始化passengers,fuelcap和mpg域。using System;class Vehicle public int passengers; /乘客數(shù) public int fuelcap; /所耗燃料public int mpg; /每英

23、里耗油量 /下面是Vehicle的一個構(gòu)造函數(shù)public Vehicle(int p,int f,int m) passengers=p; fuelcap=f; mpg=m;/返回距離數(shù)public int range() return mpg*fuelcap;/計算給定距離所要消耗的燃料public double fuelneeded(int miles) return (double) miles/mpg;class VehConsDemo public static void Main() /構(gòu)造一個完全的車輛 Vehicle minivan=new Vehicle(7,16,21);

24、 Vehicle sportscar=new Vehicle(2,14, 12); double gallons; int dist=252; gallons=minivan.fuelneeded(dist); Console.WriteLine("To go"+dist+"miles minivan needs"+gallons+"gallons of fuel."); gallons=sportscar.fuelneeded(dist); Console.WriteLine("To go"+dist+"

25、;miles sportscar needs"+gallons+"gallons of fuel."); Console.Read();結(jié)果如下:To go 252 miles minivan needs 12 gallons of fuel.To go 252 miles sportscar needs 21 gallons of fuel.當(dāng)minivan和sportscar被創(chuàng)建時,它們都會被構(gòu)造函數(shù)Vehicle()初始化。每個對象都被構(gòu)造函數(shù)中指定的參數(shù)初始化。關(guān)于構(gòu)造函數(shù)還必須說明以下幾點:和普通函數(shù)一樣,構(gòu)造函數(shù)也可以有參數(shù),但是構(gòu)造函數(shù)不能有返回值

26、。這是因為構(gòu)造函數(shù)通常是在定義一個新的對象時調(diào)用,它無法檢查構(gòu)造函數(shù)的返回值。在實際應(yīng)用中,通常都需要給一個類定義構(gòu)造函數(shù),但是,類沒有構(gòu)造函數(shù)也是允許的。如果沒有給類定義構(gòu)造函數(shù),則編譯系統(tǒng)將為該類生成一個默認(rèn)的構(gòu)造函數(shù)。這個默認(rèn)的構(gòu)造函數(shù)沒有參數(shù),它只是簡單的把對象中的每個實例變量初始化為0。構(gòu)造函數(shù)可以有默認(rèn)參數(shù)。在這種情況下,定義對象可以使用默認(rèn)參數(shù)。當(dāng)然構(gòu)造函數(shù)也可以沒有參數(shù)。3.2.4 析構(gòu)函數(shù)可以定義一個方法,讓它在對象被垃圾回收器破壞前調(diào)用。這樣的方法叫做析構(gòu)函數(shù)(destructor),它能確保對象干凈的終止。析構(gòu)函數(shù)也是類中的特殊成員函數(shù),與定義它的類具有相同的名字,但要在

27、前面加上“”。析構(gòu)函數(shù)沒有參數(shù),也沒有返回值,而且也不能重載,因此一個類中只能有一個析構(gòu)函數(shù)。析構(gòu)函數(shù)執(zhí)行與構(gòu)造函數(shù)相反的操作,通常用于釋放分配給對象的存儲空間。當(dāng)程序超出類對象的作用域時,或者當(dāng)對一個類指針使用運算符delete時,系統(tǒng)將自動調(diào)用析構(gòu)函數(shù)。和構(gòu)造函數(shù)一樣,如果在類的定義中不定義析構(gòu)函數(shù),編譯系統(tǒng)將為之產(chǎn)生一個默認(rèn)的析構(gòu)函數(shù),對于大多數(shù)類來說,默認(rèn)的析構(gòu)函數(shù)就能滿足要求。如果在一個對象完成其操作之前還需要做一些內(nèi)部處理,則應(yīng)顯示的定義析構(gòu)函數(shù)。定義析構(gòu)函數(shù)的基本格式如下所示:attributes identifier() block;其中的attribute用于指定析構(gòu)函數(shù)的特

28、征,block用于定義析構(gòu)函數(shù)的具體實現(xiàn)的程序塊。例3-5 這是一個以計算員工工資的程序來說明構(gòu)造函數(shù)和析構(gòu)函數(shù)的使用。using System;class EmpClass /定義類EmpClass /結(jié)構(gòu)體EmpNameAge作為類EmpClass的私有成員,該結(jié)構(gòu)體中保存職工信息 public struct EmpInfo public string Name; public int Age; /結(jié)構(gòu)體EmpWage中保存職工的工資信息 public struct EmpWage public double Days; public double RegSal; public doubl

29、e OverSal; public EmpInfo emp; public EmpWage empwage; public EmpClass() /類EmpClass的構(gòu)造函數(shù) Console.WriteLine("對象生成"); EmpClass() /類EmpClass的析構(gòu)函數(shù) Console.WriteLine("對象消失"); public void InfoIn() /定義類EmpClass中的InfoIn方法 Console.Write("輸入姓名:t"); emp.Name = Console.ReadLine();

30、Console.Write("輸入年齡:t"); emp.Age = int.Parse(Console.ReadLine(); Console.Write("輸入工作天數(shù):t"); empwage.Days = double.Parse(Console.ReadLine(); Console.Write("輸入每天工資:t"); empwage.RegSal = double.Parse(Console.ReadLine(); Console.Write("輸入加班工資:t"); empwage.OverSal

31、= double.Parse(Console.ReadLine(); public void InfoOut() /定義類EmpClass中的InfoOut方法 double wage; if (empwage.Days > 23) wage = empwage.Days * empwage.RegSal + (empwage.Days - 23) * empwage.OverSal; else wage = empwage.Days * empwage.RegSal; Console.WriteLine("0的工資總額為t1", emp.Name, wage); ;

32、public class test static int Main() EmpClass Widget = new EmpClass(); Widget.InfoIn(); Widget.InfoOut(); Console.ReadLine(); return 0; 結(jié)果如下:對象生成輸入姓名: WangHong輸入年齡: 26輸入工作天數(shù): 25輸入每天工資: 100輸入加班工資: 200WangHong的工資總額為 2900上述程序中定義了一個類EmpClass,該類中包含了兩個結(jié)構(gòu)體,并定義了兩個成員函數(shù)以及構(gòu)造函數(shù)和析構(gòu)函數(shù)。兩個成員函數(shù)分別用來輸入輸出職工的姓名、年齡等信息。規(guī)定每

33、月工作23天,超過23天按加班處理。類EmpClass中還嵌套定義了兩個結(jié)構(gòu)體。C#規(guī)定,嵌套結(jié)構(gòu)體(或類)的定義如果位于類的公有部分,則可以由類以外的變量訪問。也就是說,嵌套結(jié)構(gòu)體(或類)的可見性與把該結(jié)構(gòu)體(或類)定義在類外是相同的。在類EmpClass只定義了構(gòu)造函數(shù)和析構(gòu)函數(shù),它們都沒有參數(shù),只顯示一行信息。從程序的執(zhí)行過程可以看出,程序在聲明EmpClass類的對象時自動調(diào)用構(gòu)造函數(shù),在結(jié)束應(yīng)用程序時自動調(diào)用析構(gòu)函數(shù)。3.3方法類的兩個主要組成部分是實例變量和方法。方法是操作類定義的數(shù)據(jù)的子程序,它提供一種訪問數(shù)據(jù)的途徑。很明顯,程序的其它部分將通過方法和類進行交互。一個方法可以包含

34、一條或多條語句。在編寫良好的C#代碼中,每個方法僅僅完成一項任務(wù)。每個方法都有一個名字,這個名字被用來調(diào)用該方法。然而,記住Main()是一個保留方法,它用來開始的執(zhí)行,并且不要用C#的關(guān)鍵字來命名方法。方法名后緊跟著一對括號。例如,如果有一個方法叫g(shù)etval,那么在某個語句中要使用該方法名的時候,我們寫成getval()。方法的一般形式如下所示: access ret-type name(parameter-list) /方法體 這里access是訪問說明符,它用來控制程序的哪些部分可以調(diào)用該方法。如果忽略訪問說明符,該方法將為該方法所在類的私有成員。ret-type指定該方法返回數(shù)據(jù)的類

35、型,它可以是任何有效地類型,包括自定義類類型。如果方法不返回一個值,其返回類型必須是void。方法名由name指定。name可以是在目前范圍內(nèi)還沒有被使用的任何合法的標(biāo)識符。parameter-list是用逗號隔開的類型、標(biāo)識符。型參(parameter)本質(zhì)上是一個變量,它用來在調(diào)用方法時接收實參(arguments)傳給方法的值。如果方法沒有參數(shù),那么參數(shù)列表為空。例3-6 在類Vehicle中添加一個方法range()來顯示車輛的行駛距離using System;class Vehicle public int passengers; /乘客數(shù) public int fuelcap; /

36、所耗燃料public int mpg; /每英里耗油量/顯示距離public void range() Console.WriteLine("Range is "+fuelcap*mpg); /這個類聲明了類型Vehicle的一個對象class AddMeth public static void Main() Vehicle minivan=new Vehicle(); Vehicle sportscar=new Vehicle(); /給minivan的各個域賦值 minivan.passengers=7; minivan.fuelcap=16; minivan.mpg

37、=21; /給sportscar的各個域賦值 sportscar.passengers=2; sportscar.fuelcap=14; sportscar.mpg=12; Console.Write("Minivan can carry "+minivan.passengers+". "); minivan.range(); Console.Write("Sportscar can carry "+ sportscar.passengers+". "); sportscar.range(); Console.Re

38、ad();結(jié)果如下:Minivan can carry 7. Range is 336 Sportscar can carry 2. Range is 168首先來看range()方法。方法range()的第一行是: public void range()這行代碼聲明了一個叫range方法,它沒有參數(shù),并被指定為public,因此它能被程序的任何其他部分使用。該方法的返回類型為void。也就是說方法range()不給調(diào)用者返回任何值range()的體下面這條語句組成:Console.WriteLine(“Range is”+fuelcap*mpg);這行語句通過fuelcap乘以mpg來計算車

39、輛的行駛距離,并且顯示該值。由于每個Vehicle對象都有其自身的fuelcap和mpg拷貝,因此,當(dāng)調(diào)用方法range()時,對行駛距離的計算將調(diào)用對象自身的這些變量的拷貝。再來研究這一行代碼:minivan.range();這行語句在minivan上調(diào)用range()方法。也就是說,它在對象名后緊跟點運算符來調(diào)用與對象minivan相關(guān)的方法range()。當(dāng)調(diào)用一個方法時,程序控制交給了該方法。當(dāng)該方法結(jié)束時,程序控制又回到調(diào)用者,繼續(xù)執(zhí)行方法后面的代碼行。在方法range()中有些非常重要的東西是值得注意的:比如我們并沒有使用點運算符來引用實例變量fuelcap和mpg,而是直接使用該

40、變量。當(dāng)在類的方法中使用該類定義的實例變量時,可以直接使用,而不必使用點運算符。因為一個方法一般是由該類的一個對象所調(diào)用的。一旦要調(diào)用方法,這個對象就是確定的。因此,在方法內(nèi)部沒有必要第二次指定對象。這就意味著在方法range()中使用fuelcap和mpg是調(diào)用該方法的對象所包含的變量。一般來說有兩種情況將導(dǎo)致方法返回。第一種情況:當(dāng)碰到方法的結(jié)束花括號,如同前面的例子中從range()方法返回一樣。第二種情況:執(zhí)行到return語句。有兩種形式的return:一種用在void方法中,另一種用在有返回值的方法中。在一個void方法中,可以用下述形式的return語句來立即結(jié)束一個方法: re

41、turn;當(dāng)執(zhí)行該語句時,程序控制返回到調(diào)用者,跳過方法中任何剩余的代碼。例如: public void MyMeth() int i; for(i=0;i<10;i+) if(i=5) return ; /i=5時停止 Console.WriteLine(); 這里for循環(huán)僅僅從0運行到5,因為一旦i等于5,該方法將返回。C#允許在一個方法中有兩個或多個return語句,特別是當(dāng)方法有多個分支時。例如: public void MyMeth() if(done) return; / if(error) return; 這時,當(dāng)done為真或方法出錯(error)時,都從方法中返回。一

42、個void方法在下述情況之一下將返回:程序執(zhí)行時碰到方法的結(jié)束花括號,或者程序執(zhí)行到一條return語句時。3.3.2方法的參數(shù) 返回值在編程時方法的返回值有各種各樣的作用。有時返回值包含某種計算的輸出結(jié)果,比如Math.Sqrt()方法;有時返回值簡單標(biāo)識方法執(zhí)行的成功與否;還有些情況返回值包含一個的狀態(tài)碼。使用下述形式的return語句來從一個值給調(diào)用者: return value; 這里value是要從方法中返回的值??梢允褂梅祷刂祦砀倪Mrange()方法。更好的實現(xiàn)是讓方法range()計算行駛距離并返回這個值,而不是顯示該值。這樣的一個優(yōu)點之一是可以把該返回值用于其他計算。例3-7

43、下面的例子修改了range()方法,并返回行駛距離而不是顯示行駛距離:using System;class Vehicle public int passengers; /乘客數(shù) public int fuelcap; /所耗燃料 public int mpg; /每英里耗油量 / 顯示距離 public int range() return fuelcap * mpg; /這個類聲明了類型Vehicle的一個對象class RetMeth public static void Main() Vehicle minivan = new Vehicle(); Vehicle sportscar

44、= new Vehicle(); int range1, range2; /給minivan的各個域賦值 minivan.passengers = 7; minivan.fuelcap = 16; minivan.mpg = 21; /給sportscar的各個域賦值 sportscar.passengers = 2; sportscar.fuelcap = 14; sportscar.mpg = 12; range1 = minivan.range(); range2 = sportscar.range(); Console.WriteLine("Minivan can carry

45、" + minivan.passengers.ToString() + "with range of " + range1.ToString() + "miles."); Console.WriteLine("Sportscar can carry" + sportscar.passengers.ToString() + "with range of " + range2.ToString() + "miles."); Console.Read(); 結(jié)果如下:Minivan can

46、carry 7 with range of 336 miles. Sportscar can carry 2with range of 168 miles.注意,在上面的程序中,當(dāng)調(diào)用range()方法時,是把它放在賦值語句的右邊。賦值語句的左邊是一個變量,用來接收方法range()返回的值。因此,下面這行語句執(zhí)行后:range1=minivan.range();minivan對象的行駛距離將被存儲在range1中。注意,現(xiàn)在方法range()有一個int類型的返回值。這意味著它將返回一個整數(shù)值給調(diào)用者。方法返回值的類型是非常重要的,因為返回數(shù)據(jù)的類型必須與該方法定義時指定的返回數(shù)據(jù)類型相一致

47、。因此,如果需要方法返回一個double型數(shù)據(jù),那么方法的返回類型必須是double類型。使用參數(shù)調(diào)用方法時可以給該方法傳遞一個或多個值。已經(jīng)解釋過,傳給方法的值叫做實參(argument)。在方法內(nèi)部,接受實參值的變量叫做形參(parameter)。型參在緊跟著方法名的括號中聲明。形參的聲明語法與變量的聲明語法一樣。形參只在方法內(nèi)部有效,除了接受實參的值以外,它與局部變量沒有什么區(qū)別。例3-8 下面是一個使用參數(shù)的簡單例子。在類ChkNum中,如果傳給方法isEven()的值是偶數(shù),該方法返回true,否則返回false。因此,方法isEven()有一個bool型的返回值。using Sys

48、tem;class ChkNum public bool isEven(int x) /這里x是方法isEven()的一個整形參數(shù),如果x是偶數(shù)返回真 if(x%2)=0) return true; else return false; class ParmDemo public static void Main() ChkNum e = new ChkNum(); if(e.isEven(10) Console.WriteLine("10 is even."); if(e.isEven(9) Console.WriteLine("9 is even."

49、); if(e.isEven(8) Console.WriteLine("8 is even."); Console.Read(); 結(jié)果輸出如下:10 is even. 8 is even.在程序中三次調(diào)用了方法isEven(),每一次都傳遞了一個不同的值。首先,請注意是怎樣調(diào)用isEven()方法的。參數(shù)值是在方法名后的括號中指定的。當(dāng)?shù)谝淮握{(diào)用isEven()方法時,它傳遞了值10。因此,當(dāng)isEven()開始執(zhí)行時,參數(shù)x接受10;第二次調(diào)用時傳遞值9,此時x接受值9;第三次調(diào)用時傳遞值8,此時x接受值8。方法可以有多個參數(shù),這時只需分別聲明各個參數(shù),并且用逗號把它

50、們隔開。例如下面的類Factor定義了一個方法isFactor(),它判斷第一個參數(shù)是否是第二個參數(shù)的因子。using System;class Factor public bool isFactor(int a,int b) if(b%a)=0) return true; else return false; class IsFact public static void Main() Factor x=new Factor(); if(x.isFactor(2,20) Console.WriteLine(“2 is factor”); if(x.isFactor(3,20) Console

51、.WriteLine(“this wont be displayed”); 例3-9 使用帶參數(shù)的方法來為類Vehicle增加新的特性:計算指定距離的耗油量。這個新的方法叫做fuelneeded()。這個方法根據(jù)你要行駛的距離數(shù),返回需要的汽油加侖數(shù)。方法fuelneeded()的定義如下: public double fuelneeded(int miles) return (double) miles/mpg;注意,該方法返回一個double型值。由于需要的燃料體積可能不是一個整數(shù),這是很有用的。一個完整的包含fuelneeded()方法的Vehicle類如下所示: using Syste

52、m;class Vehicle public int passengers; /乘客數(shù) public int fuelcap; /所耗燃料public int mpg; /每英里耗油量/返回的距離數(shù)public int range() return mpg*fuelcap;/計算給定距離所需要的燃料public double fuelneeded(int miles) return (double) miles/mpg; /這個類聲明了類型Vehicle的一個對象class ComFuel public static void Main() Vehicle minivan=new Vehicle(); Vehicle sportscar=new Vehicle(); double gallons; int dist=252; /給minivan的各個域賦值 minivan.passengers=7; minivan.fuelcap=16; minivan.mpg=21; /給sportscar的各個域賦值 sportscar.passengers

溫馨提示

  • 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

提交評論