深入剖析C#繼承機制6

五、繼承與訪問修飾符

  訪問修飾符是一些關鍵字,用於指定聲明的成員或類型的可訪問性。類的繼承中有四個訪問修飾符: public protected internal private。使用這些訪問修飾符可指定下列五個可訪問性級別: public protected internal internal protected private。

聲明的可訪問性 意義
public 訪問不受限制。
protected 訪問僅限於包含類或從包含類派生的類型。
internal 訪問僅限於當前項目。
protected internal 訪問僅限於從包含類派生的當前項目或類型。
private 訪問僅限於包含類型。

  1、繼承中關於可訪問域的一些問題

  基類的所有成員(實例構造函數、析構函數和靜態構造函數除外)都由派生類型繼承。這甚至包括基類的私有成員。但是,私有成員的可訪問域只包括聲明該成員的類型的程序文本。在下面的示例中

class A
{
int x ;
static void F(B b) {
b.x = 1 ; // 對
}
}
class B: A
{
static void F(B b) {
b.x = 1 ; // 錯誤
}
}

  類 B 繼承類 A 的私有成員 x。因爲該成員是私有的,所以只能在 A 的"類體"中對它進行訪問。因此,對 b.x 的訪問在 A.F 方法中取得了成功,在 B.F 方法中卻失敗了。

  2、繼承中關於屬性的一些問題

  和類的成員方法一樣,我們也可以定義屬性的重載、虛屬性、抽象屬性以及密封屬性的概念。與類和方法一樣,屬性的修飾也應符合下列規則:

  屬性的重載

  1. 在派生類中使用修飾符的屬性,表示對基類中的同名屬性進行重載。

  2. 在重載的聲明中,屬性的名稱、類型、訪問修飾符都應該與基類中被繼承的屬性一致。

  3. 如果基類的屬性只有一個屬性訪問器,重載後的屬性也應只有一個。但如果基類的屬性同時包含get 和set 屬性訪問器,重載後的屬性可以只有一個,也可以同時有兩個屬性訪問器。

  注意:與方法重載不同的是,屬性的重載聲明實際上並沒有聲明新的屬性,而只是爲已有的虛屬性提供訪問器的具體實現。

  虛屬性

  1. 使用virtual 修飾符聲明的屬性爲虛屬性。

  2. 虛屬性的訪問器包括get 訪問器和set 訪問器,同樣也是虛的。

  抽象屬性

  1. 使用abstract 修飾符聲明的屬性爲抽象屬性。

  2. 抽象屬性的訪問器也是虛的,而且沒有提供訪問器的具體實現。這就要求在非虛的派生類中,由派生類自己通過重載屬性來提供對訪問器的具體實現。

  3. abstract 和override 修飾符的同時使用,不但表示屬性是抽象的,。而且它重載了基類中的虛屬性這時屬性的訪問器也是抽象的。

  4. 抽象屬性只允許在抽象類中聲明。

  5. 除了同時使用abstract 和override 修飾符這種情況之外,static, virtual, override和abstract 修飾符中任意兩個不能再同時出現。

  密封屬性

  1. 使用sealed 修飾符聲明的屬性爲密封屬性。類的密封屬性不允許在派生類中被繼承。密封屬性的訪問器同樣也是密封的。

  2. 屬性聲明時如果有sealed 修飾符,同時也必須要有override 修飾符。

  從上面可以看出,屬性的這些規則與方法十分類似。對於屬性的訪問器,我們可以把get 訪問器看成是一個與屬性修飾符相同、沒有參數、返回值爲屬性的值類型的方法,把set 訪問器看成是一個與屬性修飾符相同、僅含有一個value 參數、返回類型爲void 的方法。看下面的程序:

using System ;
public enum sex
{ woman, man, } ;
abstract public class People
{
private string s_name;
public virtual string Name
{
get
{ return s_name ; }
}
private sex m_sex ;
public virtual sex Sex
{
get
{ return m_sex ; }
protected string s_card;
public abstract string Card
{ get; set; }
}

  上面的例子中聲明瞭"人"這個類,人的姓名Name 和性別Sex 是兩個只讀的虛屬性:身份證號Card 是一個抽象屬性,允許讀寫,因爲類People 中包含了抽象屬性Card,所以People 必須聲明是抽象的。下面我們爲住宿的客人編寫一個類類從People 中繼承。再看下面的程序:

class Customer: People
{
string s_no ;
int i_day ;
public string No
{
get
{ return s_no ; }
set
{
if (s_no != value)
s_no = value;
}
}
public int Day
{
get
{ return i_day ; }
set
{
if (i_day != value)
i_day = value;
}
}
public override string Name
{
get { return base.Name; }
}
public override sex Sex
{
get { return base.Sex }
}
public override string Card
{
get
{ return s_ card ; }
set
{ s_ card = value ; }
}
}

  在類Customer 中,屬性Name、 Sex 和Card 的聲明都加上了override 修飾符,屬性的聲明都與基類People 中保持一致。Name 和Sex 的get 訪問器,Card 的get 和set訪問器都使用了base 關鍵字來訪問基類People 中的訪問器屬性。Card 的聲明重載了基類People 中的抽象訪問器。這樣,在Customer 類中沒有抽象成員的存在,Customer可以是非虛的。

發佈了29 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章