Net面向?qū)ο蟪绦蛟O(shè)計-15-實現(xiàn)屬性以訪問字段-2010-2011-2_第1頁
Net面向?qū)ο蟪绦蛟O(shè)計-15-實現(xiàn)屬性以訪問字段-2010-2011-2_第2頁
Net面向?qū)ο蟪绦蛟O(shè)計-15-實現(xiàn)屬性以訪問字段-2010-2011-2_第3頁
Net面向?qū)ο蟪绦蛟O(shè)計-15-實現(xiàn)屬性以訪問字段-2010-2011-2_第4頁
Net面向?qū)ο蟪绦蛟O(shè)計-15-實現(xiàn)屬性以訪問字段-2010-2011-2_第5頁
已閱讀5頁,還剩26頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、.NET.NET面向?qū)ο蟪绦蛟O(shè)計面向?qū)ο蟪绦蛟O(shè)計第第1515章章實現(xiàn)屬性以訪問字段實現(xiàn)屬性以訪問字段本章簡介本章簡介使用屬性封裝邏輯字段使用屬性封裝邏輯字段聲明聲明get accessor聲明聲明set accessor創(chuàng)建聲明了屬性的接口創(chuàng)建聲明了屬性的接口使用結(jié)構(gòu)和類實現(xiàn)含有屬性的接口使用結(jié)構(gòu)和類實現(xiàn)含有屬性的接口根據(jù)字段定義自動生成屬性根據(jù)字段定義自動生成屬性用屬性來初始化對象用屬性來初始化對象15.1 使用方法來實現(xiàn)封裝使用方法來實現(xiàn)封裝 以下結(jié)構(gòu)用于將屏幕上的一個位以下結(jié)構(gòu)用于將屏幕上的一個位置表示成一個(置表示成一個(X,Y)坐標對)坐標對 假定假定x坐標的取值范圍是坐標的取值范圍

2、是01280,y的取值范圍是的取值范圍是01024 private static int rangeCheckedX(int x) if (x 1280) throw new ArgumentOutOfRangeException(X); return x; private static int rangeCheckedY(int y) if (y 1024) throw new ArgumentOutOfRangeException(Y); return y; struct ScreenPosition public int X; public int Y; public ScreenPos

3、ition(int x, int y) this.X = rangeCheckedX(x); this.Y = rangeCheckedY(y); 問題:違反了封裝的原則,沒有將其數(shù)據(jù)保持問題:違反了封裝的原則,沒有將其數(shù)據(jù)保持private狀態(tài)狀態(tài) 雖然雖然ScreenPosition構(gòu)造器會對它的參數(shù)進行范圍構(gòu)造器會對它的參數(shù)進行范圍檢查,但在創(chuàng)建好一個對象后,就可以隨便訪問檢查,但在創(chuàng)建好一個對象后,就可以隨便訪問public字段字段ScreenPosition origin = new ScreenPosition(0, 0); . int xpos = origin.X; origi

4、n.Y = -100; / oops 解決該問題的方法:將字解決該問題的方法:將字段設(shè)為段設(shè)為private,并添加一,并添加一個取值(個取值(getr accessor)方 法 和 一 個 賦 值 (方 法 和 一 個 賦 值 ( s e t accessor)方法,以便分)方法,以便分別讀取和寫入每個別讀取和寫入每個private字段的值字段的值 然后,賦值方法就可以對然后,賦值方法就可以對新的字段值執(zhí)行范圍檢查新的字段值執(zhí)行范圍檢查 缺點:它使用的是不太方缺點:它使用的是不太方便的,基于方法的語法便的,基于方法的語法uint xpos = origin.GetX(); uorigin.S

5、etX(xpos + 10);struct ScreenPosition . public int GetX() return this.x; public void SetX(int newX) this.x = rangeCheckedX(newX); . private static int rangeCheckedX(int x) . private static int rangeCheckedY(int y) . private int x, y; 15.2 什么是屬性什么是屬性 屬性(屬性(property)是字段)是字段和方法的一個交集:和方法的一個交集:它看它看起來像是一個字

6、段,行為起來像是一個字段,行為上又像一個方法上又像一個方法 訪問一個屬性所用的語法訪問一個屬性所用的語法和訪問一個字段的語法是和訪問一個字段的語法是相同的相同的 編譯器會將這種字段風(fēng)格編譯器會將這種字段風(fēng)格的語法自動轉(zhuǎn)換成對特定的語法自動轉(zhuǎn)換成對特定accessor方法的調(diào)用方法的調(diào)用 語法:語法:AccessModifier Type propertyName get / read accessor code set / write accessor code struct ScreenPosition private int x, y; public ScreenPosition(int

7、X, int Y) this.x = rangeCheckedX(X); this.y = rangeCheckedY(Y); public int X get return this.x; set this.x = rangeCheckedX(value); public int Y get return this.y; set this.y = rangeCheckedY(value); private static int rangeCheckedX(int x) . private static int rangeCheckedY(int y) . 注意:注意:u所有所有set acc

8、essor都用一個隱藏的、都用一個隱藏的、內(nèi)建的參數(shù)來傳遞內(nèi)建的參數(shù)來傳遞要寫入的數(shù)據(jù)要寫入的數(shù)據(jù)upublic字段和屬性字段和屬性大寫,大寫,private的字的字段和屬性小寫段和屬性小寫屬性為訪問對象內(nèi)的實例變量及訪問另一個對象屬性為訪問對象內(nèi)的實例變量及訪問另一個對象中的實例變量提供了一致性的語法。中的實例變量提供了一致性的語法。屬性與等價的存取器方法執(zhí)行速度同樣快。屬性與等價的存取器方法執(zhí)行速度同樣快。當屬性的當屬性的get語句塊和語句塊和set語句塊編譯成語句塊編譯成MSIL時,時,它們都轉(zhuǎn)換成方法。在它們都轉(zhuǎn)換成方法。在MSIL中,中,get語句塊由一語句塊由一個名字為個名字為ge

9、t_的方法表示。的方法表示。set同樣。同樣。815.2.1 使用屬性使用屬性從從ScreenPosition結(jié)構(gòu)的結(jié)構(gòu)的X和和Y屬性中取值:屬性中取值:uScreenPosition origin = new ScreenPosition(0, 0);uint xpos = origin.X; / calls origin.X.get uint ypos = origin.Y; / calls origin.Y.get對屬性進行賦值,編譯器自動將字段風(fēng)格的代碼對屬性進行賦值,編譯器自動將字段風(fēng)格的代碼轉(zhuǎn)換成對該屬性的轉(zhuǎn)換成對該屬性的set accessor的調(diào)用的調(diào)用uorigin.X =

10、40; / calls origin.X.set, with value set to 40 uorigin.Y = 100; / calls origin.Y.Set, with value set to 100可以通過可以通過static關(guān)鍵字聲明靜態(tài)屬性,訪問關(guān)鍵字聲明靜態(tài)屬性,訪問static屬性時,要附加類或者結(jié)構(gòu)的名稱而不是其實例屬性時,要附加類或者結(jié)構(gòu)的名稱而不是其實例的名稱作為前綴的名稱作為前綴15.2.2 只讀屬性只讀屬性 可以聲明只包含一個可以聲明只包含一個get accessor的屬性,即聲明了的屬性,即聲明了一個只讀屬性一個只讀屬性 X屬性不包含屬性不包含set acc

11、essor,所以,如下操作錯誤,所以,如下操作錯誤 origin.X = 140; / compile-time error示例:示例:struct ScreenPosition . public int X get return this.x; 15.2.3 只寫屬性只寫屬性 也可以聲明只包含一個也可以聲明只包含一個set accessor的屬性,即聲明的屬性,即聲明了一個只寫屬性了一個只寫屬性 X 屬 性 不 包 含屬 性 不 包 含 g e t accessor,所以,如下操,所以,如下操作錯誤作錯誤Console.WriteLine(origin.X); / 編譯器編譯器error o

12、rigin.X = 200; / OK origin.X += 10;/ 編譯器編譯器error示例:示例:struct ScreenPosition . public int X set this.x = rangeCheckedX(value); 只寫屬性適用于對密碼這只寫屬性適用于對密碼這樣的屬性進行保護樣的屬性進行保護15.2.4 屬性的可訪問性屬性的可訪問性可訪問性是在聲明屬性時指定的,但是,在屬性可訪問性是在聲明屬性時指定的,但是,在屬性的聲明中,可以為的聲明中,可以為get和和set單獨指定可訪問性單獨指定可訪問性struct ScreenPosition public int

13、X get return this.x; private set this.x = rangeCheckedX(value); public int Y get return this.y; private set this.y = rangeCheckedY(value); private int x, y; 注意:注意:u定義時,只能改變一個定義時,只能改變一個accessor的可訪問性的可訪問性uaccessor的訪問修飾符所指定的可訪問性在限制程度的訪問修飾符所指定的可訪問性在限制程度上必須大于屬性的可訪問性上必須大于屬性的可訪問性警告:警告:u習(xí)慣上,為屬性和習(xí)慣上,為屬性和priv

14、ate字段賦予幾乎完全相同的名字段賦予幾乎完全相同的名稱,只是首字母大小寫有別稱,只是首字母大小寫有別u但是,要小心使用但是,要小心使用class Employee private int employeeID; public int EmployeeID; get return this.EmployeeID; set this.EmployeeID = value; 15.3 理解屬性的局限性理解屬性的局限性屬性在外觀、行為和感覺上都類似于字段,但它屬性在外觀、行為和感覺上都類似于字段,但它們本質(zhì)上是方法,并不是真正的字段們本質(zhì)上是方法,并不是真正的字段屬性的限制:屬性的限制:u只有在一個

15、結(jié)構(gòu)或類初始化好之后,才能通過這個結(jié)只有在一個結(jié)構(gòu)或類初始化好之后,才能通過這個結(jié)構(gòu)或類的屬性來進行賦值構(gòu)或類的屬性來進行賦值ScreenPosition location; location.X = 40; / compile-time error, location not assignedu所以,定義結(jié)構(gòu)和類時,一開始就應(yīng)該使用屬性,而所以,定義結(jié)構(gòu)和類時,一開始就應(yīng)該使用屬性,而不是先用字段,后來又變成屬性,字段變成屬性后,不是先用字段,后來又變成屬性,字段變成屬性后,以前使用了這個類或結(jié)構(gòu)的代碼就可能無法正常工作以前使用了這個類或結(jié)構(gòu)的代碼就可能無法正常工作u不能將屬性作為一個不能將

16、屬性作為一個ref或者或者out參數(shù)值傳給一個方法;參數(shù)值傳給一個方法;但可以將一個可寫的字段作為但可以將一個可寫的字段作為ref或或out參數(shù)值傳遞,這參數(shù)值傳遞,這是因為屬性并不真正指向一個內(nèi)存位置,它代表的是一是因為屬性并不真正指向一個內(nèi)存位置,它代表的是一個方法個方法u在一個屬性中,最多只能包含一個在一個屬性中,最多只能包含一個get accessor和一個和一個set accessor,屬性不能包含其他方法、字段或?qū)傩?,屬性不能包含其他方法、字段或?qū)傩評get accessor和和set accessor不能獲取任何參數(shù),要賦不能獲取任何參數(shù),要賦的值會通過內(nèi)建的、隱藏的的值會通過內(nèi)

17、建的、隱藏的value變量,自動傳給變量,自動傳給set accessoru不能聲明不能聲明const屬性屬性合理使用屬性合理使用屬性class BankAccount . public money Balance get . set . private money balance; class BankAccount . public money Balance get . public void Deposit(money amount) . public bool Withdraw(money amount) . private money balance; 15.4 在接口中聲明屬性在

18、接口中聲明屬性除了可在接口中聲明方法之外,還可以定義屬性除了可在接口中聲明方法之外,還可以定義屬性interface IScreenPosition int X get; set; int Y get; set; 實現(xiàn)該接口的任何類或結(jié)構(gòu)都必須實現(xiàn)實現(xiàn)該接口的任何類或結(jié)構(gòu)都必須實現(xiàn)X和和Y屬性屬性,并在屬性中定義,并在屬性中定義get和和setstruct ScreenPosition : IScreenPosition . public int X get . set . public int Y get . set . . 在類中實現(xiàn)接口屬性時,可以將屬性的實現(xiàn)聲明在類中實現(xiàn)接口屬性時,可

19、以將屬性的實現(xiàn)聲明為為virtual,以允許未來派生的類重寫這些實現(xiàn),以允許未來派生的類重寫這些實現(xiàn)例如:例如:class ScreenPosition : IScreenPosition public virtual int X get . set . public virtual int Y get . set . 還可以選擇使用顯式接口實現(xiàn)語法來實現(xiàn)一個屬還可以選擇使用顯式接口實現(xiàn)語法來實現(xiàn)一個屬性,屬性的顯式實現(xiàn)是非公共和非虛的(因而不性,屬性的顯式實現(xiàn)是非公共和非虛的(因而不能被重寫)能被重寫)struct ScreenPosition : IScreenPosition int I

20、ScreenPosition.X get . set . int IScreenPosition.Y get . set . private int x, y; 課本課本276頁練習(xí)頁練習(xí)15.5 生成自動屬性生成自動屬性屬性的兩個主要優(yōu)勢:屬性的兩個主要優(yōu)勢:u與應(yīng)用程序的兼容性與應(yīng)用程序的兼容性u與接口的兼容性:如果要實現(xiàn)一個接口,而且接口將與接口的兼容性:如果要實現(xiàn)一個接口,而且接口將一個數(shù)據(jù)項定義成屬性,就必須實現(xiàn)這個屬性,使之一個數(shù)據(jù)項定義成屬性,就必須實現(xiàn)這個屬性,使之與接口中的規(guī)范相符與接口中的規(guī)范相符C#編譯器能夠自動為屬性生成代碼編譯器能夠自動為屬性生成代碼class Cir

21、cle public int Radius get; set; . 自動生成的屬性不可以是自動生成的屬性不可以是只讀或者只寫的只讀或者只寫的class Circle private int _radius; public int Radius get return this._radius; set this._radius = value; . 15.6 使用屬性來初始化對象使用屬性來初始化對象public class Triangle private int side1Length; private int side2Length; private int side3Length; pub

22、lic Triangle() this.side1Length = this.side2Length = this.side3Length = 10; public Triangle(int length1) this.side1Length = length1; this.side2Length = this.side3Length = 10; public Triangle(int length1, int length2) this.side1Length = length1; this.side2Length = length2; this.side3Length = 10; publ

23、ic Triangle(int length1, int length2, int length3) this.side1Length = length1; this.side2Length = length2; this.side3Length = length3; 可以使用命名參數(shù),然而更好和更透明的方式是將私有變可以使用命名參數(shù),然而更好和更透明的方式是將私有變量初始化為它們的默認值并定義屬性量初始化為它們的默認值并定義屬性public class Triangle private int side1Length = 10; private int side2Length = 10; p

24、rivate int side3Length = 10; public int Side1Length set this.side1Length = value; public int Side2Length set this.side2Length = value; public int Side3Length set this.side3Length = value; Triangle tri1 = new Triangle Side3Length = 15 ; Triangle tri2 = new Triangle Side1Length = 15, Side3Length = 20

25、; Triangle tri3 = new Triangle Side2Length = 12, Side3Length = 17 ; Triangle tri4=new TriangleSide1Length=9,Side2Length=12,Side3Length = 15 ;24應(yīng)用應(yīng)用:使用屬性實現(xiàn)延遲初始化和惰性更新使用屬性實現(xiàn)延遲初始化和惰性更新當一個變量很少使用而且它的初始化即浪費時間當一個變量很少使用而且它的初始化即浪費時間又浪費資源時,可使用延遲初始化技術(shù)。又浪費資源時,可使用延遲初始化技術(shù)。惰性更新(惰性更新(lazy update)25實例分析:實例分析:為農(nóng)產(chǎn)品商人編寫

26、程序為農(nóng)產(chǎn)品商人編寫程序要求:在合理的精度范圍內(nèi)預(yù)測不同地區(qū)來年的要求:在合理的精度范圍內(nèi)預(yù)測不同地區(qū)來年的產(chǎn)量和質(zhì)量。產(chǎn)量和質(zhì)量。相關(guān)地區(qū)相關(guān)地區(qū)10天內(nèi)降水量預(yù)測是核心參數(shù)天內(nèi)降水量預(yù)測是核心參數(shù)每次降水量預(yù)測要占用一定的每次降水量預(yù)測要占用一定的cpu時間時間每次計算從零開始,每每次計算從零開始,每20秒提供一個更新更準確秒提供一個更新更準確的預(yù)報的預(yù)報不同的作物有不同的種植季節(jié),所以用戶在每年不同的作物有不同的種植季節(jié),所以用戶在每年的特定時間只需預(yù)報其中的幾種,而且每次預(yù)報的特定時間只需預(yù)報其中的幾種,而且每次預(yù)報只限于幾個地區(qū)。只限于幾個地區(qū)。26程序源代碼:程序源代碼:CropF

27、orecaster.cs01: using System;02: using System.Timers;03:04: class WeatherForecaster05: 06: public static double CalculateRainfallDay10RegionA()07: 08: /Simulated complex calculations takes 5000 milliseconds09: System.Threading.Thread.Sleep(5000);10: Random randomizer = new Random();11: return (doubl

28、e)randomizer.Next(40,100);12: 13: 14: 2715: class CropForecaster16: 17: private double rainfallDay10RegionA;18: private bool rainfallDay10RegionANeedUpdate = true;19:20: public CropForecaster()21: 22: Timer aTimer = new Timer();23: aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);24: aTimer.I

29、nterval = 20000;25: aTimer.Enabled = true;26: 27:28: public double RainfallDay10RegionA29: 30: get31: 32: if (rainfallDay10RegionANeedUpdate)33: 34: rainfallDay10RegionA = WeatherForecaster.CalculateRainfallDay10RegionA();35: rainfallDay10RegionANeedUpdate = false;36: return rainfallDay10RegionA;37:

30、 38: else39: 40: return rainfallDay10RegionA;41: 42: 43: 2845: private double ComplexResultA()46: 47: /Arbitrary calculation involving lots of calls to rainfallDay10RegionA48: return (RainfallDay10RegionA / 2) + (RainfallDay10RegionA / 3) +49: (RainfallDay10RegionA / 4);50: 51:52: private double Com

31、plexResultB()53: 54: /Arbitrary calculation involving even more calls to rainfallDay10RegionA55: return (RainfallDay10RegionA / 10 - 100) + (RainfallDay10RegionA / 100);56: 57:58: public double WheatCropSizeInTonsInRegionA ()59: 60: /More arbitrary calculations returning a nice big result61: Console

32、.WriteLine(Commencing forecast calculations. Please wait.);62: return (ComplexResultA() / 2 + ComplexResultB() / 4 +63: ComplexResultA() * 100000;64: 65:66: public void OnTimedEvent(object source, ElapsedEventArgs e)67: 68: /This method is currently called automatically every 20 seconds69: Console.WriteLine(nnNew Update NeedednPerform another forecast?);70: rainfallDay10RegionANeedUpdate = true;71: 72: 2974: class ForecastTester75: 76: public static void Main()77: 78: string answer;79: CropForecaster myForecaster = n

溫馨提示

  • 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)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論