官术网_书友最值得收藏!

3.3 常見成員

類和結構(第4章進行介紹)都具有表示其數據和行為的成員,類的成員包括在類中聲明的所有成員,以及在該類的繼承層次結構中的所有類中聲明的所有成員(構造函數和析構函數除外)。父類中的私有成員被繼承,但是不能從派生類中訪問。

具體來說,類或結構中可包含的成員有字段、常量、屬性、方法、事件、運算符、索引器、構造函數、析構函數和嵌套類型等。這些成員的修飾符可以是public、protected、private、internal、sealed、abstract、virtual、override、readonly和const。本節將對字段、常量、屬性和方法進行詳細介紹。

3.3.1 字段

字段是在類或結構中聲明的任意類型的變量。字段可以是內置數值類型,也可以是其他類的實例。例如,日歷類可能具有一個包含當前日期的字段。在類或結構中可以擁有實例字段或者靜態字段,或者同時擁有兩者。實例字段特定于類型的實例,如果擁有T類和實例字段F,可以創建類型T的兩個對象,并修改每個對象中F的值,這不影響另一對象中的該值。相比之下,靜態字段屬于類本身,在該類的所有實例中共享。對實例A所做的更改將立刻呈現在實例B和C上(如果它們訪問該字段)。

字段通常存儲這樣的數據:該數據必須可供多個類方法訪問,并且其存儲期必須長于任何單個方法的生存期。例如,表示日歷日期的類可能有三個整數字段:一個表示月份,一個表示日期,還有一個表示年份。不在單個方法范圍外部使用的變量應在方法體自身范圍內聲明為局部變量。

在C#類中,聲明一個字段的語法如下:

    修飾符 字段類型 字段名稱

其中,修飾符可以是public、protected、private、internal、sealed、abstract、virtual、override、readonly和const。public、protected、private和internal又稱為可訪問修飾符。

【范例6】

創建公有的名稱為Animal的類,并在該類中添加一個公有字段和兩個私有字段,代碼如下。

    public class Animal
    {
        public int animalId;                       //動物ID
        private string animalTypeName;              //動物類型名稱
        private string animalName;                  //動物名稱
    }

如果要在其他類中訪問Animal類的字段,首先要創建Animal類的實例對象,然后在對象名稱之后添加一個圓點(即“.”),再添加該字段的名稱。如訪問Animal類中的animalId字段,并為其賦值,代碼如下。

    Animal animalObj = new Animal();
    animalObj.animalId = 1;

由于Animal類中的其他兩個字段animalTypeName和animalName都是private類型的,因此,在其他類(除Animal類)中不能進行訪問,也不能進行賦值。

【范例7】

聲明字段時可以用賦值運算符為字段指定初始值。如指定animalTypeName字段的默認值為“貓咪”,animalName字段的默認值是“貓咪白白”,代碼如下。

    public class Animal
    {
        public int animalId;                                  //動物ID
        private string animalTypeName = "小貓咪";          //動物類型名稱
        private string animalName = "貓咪白白";            //動物名稱
    }

3.3.2 常量

常量是在編譯時已知并在程序的生存期內不發生更改的不可變值。在C#中聲明常量需要通過const關鍵字,只有C#內置類型(System.Object除外)可以聲明為const。

使用常量時,常量必須在聲明時初始化;而且可以同時聲明多個相同類型的常量;如果不會造成循環引用,用于初始化一個常量的表達式可以引用另一個常量。為了區分常量和字段,一般情況下,將常量的名稱定義為大寫。

【范例8】

開發者在計算圓的周長和面積時,需要使用到一個固定的常量——圓周率。因此,可以將圓周率聲明為常量PI,然后在計算圓的周長和面積時直接調用。步驟如下。

(1)創建名稱是Constants的類,在該類中聲明常量PI,代碼如下。

    public class Constants
    {
        public const double PI = 3.14159;       //定義圓周率
    }

(2)在Program.cs文件的Main()方法中添加代碼,提示用戶輸入半徑并獲取用戶輸入的半徑,然后計算圓的周長和面積并在控制臺輸出,代碼如下。

    Console.Write("請輸入圓的半徑:");
    int radius = Convert.ToInt32(Console.ReadLine());  //獲取用戶輸入的半徑
    Console.WriteLine("圓的周長是:{0}", 2 * Constants.PI * radius);
    Console.WriteLine("圓的面積是:{0}", Constants.PI * radius * radius);

(3)運行Program.cs文件中的代碼測試,在控制臺中輸入半徑4并計算結果,如圖3-1所示。

圖3-1 常量的使用

用戶自定義的類型(包括類、結構和數組)不能為const,這需要使用readonly修飾符創建在運行時初始化一次即不可更改的類、結構或數組。const和readonly兩個修飾符的區別在于以下幾個方面。

(1)const字段只能在該字段的聲明中初始化。readonly字段可以在聲明或構造函數中初始化。因此,根據所使用的構造函數,readonly字段可能具有不同的值。

(2)const字段是編譯時常數,而readonly字段可用于運行時常數。

(3)const默認就是靜態的,不需要使用static聲明常量,而readonly如果設置成靜態的就必須顯式聲明。

(4)const對于引用類型的常數,可能的值只能是string和null。readonly可以是任何類型。

3.3.3 屬性

屬性可以說是字段的延伸,對于對象來說,屬性可以看作是字段,訪問屬性與訪問字段的語法和結果一樣;對于類來說,屬性是一個或兩個語句塊,它的兩個核心的代碼塊分別是get屬性訪問器和set屬性訪問器。設置屬性的值時會執行set代碼塊,取屬性的值時訪問get代碼塊。get訪問器和set訪問器都是可以省略的,不具有set訪問器的屬性是只讀屬性,不具有get訪問器的屬性是只寫屬性,同時具有這兩個訪問器的屬性是讀寫屬性,其用法和特點如下。

(1)get訪問器與方法相似。它必須返回屬性類型的值作為屬性的值,當引用屬性時,若沒有為屬性賦值,則調用get訪問器獲取屬性的值。

(2)get訪問器必須以return或throw語句終止,并且控制權不能離開訪問器。

(3)get訪問器除了直接返回字段值,還可以通過計算返回字段值。

(4)set訪問器類似于返回類型為void的方法。它使用屬性類型的value隱式參數,當對屬性賦值時,用提供新值的參數調用set訪問器。

(5)在set訪問器中,對局部變量聲明使用隱式參數名稱value是錯誤的。

注意

屬性和字段的訪問方式是相同的。與字段不同的是屬性不作為變量來分類,所以不能將屬性作為ref參數和out參數傳遞。

當一個類中的字段過多時,這些字段并不安全,而且也不一定符合開發者的要求。舉例來說,假設表示學生的Student類中包含一個age字段,該字段要求學生的年齡在12~25歲之間。通過字段指定時,如果用戶輸入的內容不合法,那么需要通過條件語句進行判斷,如果使用屬性對字段進行封裝,那么可以直接在訪問器中進行設置。

【范例9】

創建Student類,該類中包含兩個私有字段和兩個公有屬性,這兩個屬性是對字段的封裝,代碼如下。

    public class Student {
       private string name;            //學生姓名
       private int age;                //學生年齡
       public string Name {
    get { return name; }
    set { name = value; }
    }
    public int Age {
       get { return age; }
       set {
           if (age < 12 || age > 25)
              age = 25;
           else
              age = value;
       }
     }
    }

在Program.cs文件的Main()方法中添加代碼,為Student類中的字段賦值,并輸出屬性的值測試,代碼如下。

    Student stu = new Student();
    stu.Age = 100;
    Console.WriteLine("輸出年齡:{0}",stu.Age);

運行Program.cs文件查看輸出結果,內容如下。

    輸出年齡:25

從輸出代碼中可以看出,在Age屬性中對age的處理已經起了作用,因此,這里輸出的結果不是100,而是25。

屬性的訪問修飾符可以是public、private、protected和internal,除了這些可訪問修飾符,還可以使用其他的修飾符。如用static將屬性聲明為靜態的,用virtual將屬性標記為虛屬性。另外,使用sealed修飾屬性,表示屬性對派生類不再是虛擬的;使用abstract聲明屬性,表示在派生類中可以對其實現。

3.3.4 方法

方法定義類可以執行的操作。方法可以接收提供輸入數據的參數,并且可以通過參數返回輸出數據。方法還可以不使用參數而直接返回值。可以為方法指定訪問級別(如public和private)、可選修飾符(如abstract或sealed)、返回值、名稱和任何方法參數。在類或結構中聲明方法的語法如下:

    訪問級別 [可選修飾符] 返回值 名稱(參數列表){
        //方法代碼
    }

方法的參數包含在小括號中,并且多個參數之間通過逗號進行分隔。括號中可以不包含參數,如果沒有參數,則表示方法不需要參數。方法的返回值可以是內置類型(如int或double),也可以是自定義的類型;如果沒有返回值,則直接使用void。

【范例10】

創建Motorcycle類,并在該類中定義三個方法,代碼如下。

    public class Motorcycle
     {
        public void StartEngine() {
        }
        protected void AddGas(int gallons) {
        }
        public virtual int Drive(int miles, int speed) {
            return 1;
        }
     }

其中,AddGas()方法和Drive()方法中的參數稱為形式參數,即形參。在調用時,向方法中傳入的參數稱為實際參數,即實參。

一個類中可包含多個方法,有些方法之間存在著一定的關系。方法重載是指在同一個類中方法同名、參數不同、調用時根據實參的形式,選擇與它匹配的方法執行操作的一種技術。這時的參數不同包含三種情況:參數的類型不同;參數的個數不同;參數的個數相同時它們的先后順序不同。

注意

方法重載在兩種情況下會認為是同一個方法,這樣的兩個方法不可以在同一個類里,否則系統會報錯。第一種情況是返回類型不同時,方法名和參數個數、順序、類型都相同的兩個方法。第二種情況是返回類型相同時,方法名和參數個數、順序、類型都相同的方法,但是參數的名字不同。

方法重載適用于普通的方法,也適用于構造函數。決定方法是否構成重載有以下幾個條件。

(1)在同一個類中。

(2)方法名稱相同。

(3)參數列表不同。

【范例11】

在類中聲明4個名稱為GetTest的方法,代碼如下。

    protected void GetTest(){
        Console.WriteLine("方法1");
    }
    protected void GetTest(string s, int a){            //正確的方法重載
        Console.WriteLine("方法2"); 
    }
    protected void GetTest(string a, int s){
        Console.WriteLine("方法3");
    }
    protected void GetTest(int a,string s) {
        Console.WriteLine("方法3");
    }

上述所示的4個方法中,第一個和第二個是方法重載;第二個與第三個是同一個方法,因為它們只是參數的名稱不同,因此不能出現在同一個類中;第二個與第四個是正確的方法重載,因為它們參數的順序不同。

主站蜘蛛池模板: 汶川县| 乐平市| 龙南县| 右玉县| 奉新县| 淅川县| 区。| 卢龙县| 安达市| 大安市| 正定县| 翼城县| 延长县| 平凉市| 陕西省| 湟源县| 江油市| 明光市| 九龙县| 平和县| 普宁市| 驻马店市| 福建省| 青龙| 紫阳县| 台山市| 湟源县| 彭泽县| 越西县| 东宁县| 榕江县| 杨浦区| 永州市| 沽源县| 天门市| 邳州市| 吉首市| 清涧县| 安达市| 信阳市| 鹿邑县|