1. 程式人生 > >C# 類成員的高階議題

C# 類成員的高階議題

隱藏基類方法

當從基類繼承一個(非抽象的)成員時,也就繼承丁其實現程式碼。如果繼承的成雖是虛擬的,就
可以用override 關鍵字重寫這段實現程式碼。無論繼承的成員是否為虛擬,都可以隱藏這些實現程式碼。
這是很有用的,例如,當繼承的公共成員不像預期的那樣工作時,就可以隱藏它。
使用下面的程式碼就可以隱藏:

public class MyBaseClass
{
    public void DoSomething()
    {
        // Base implementation.
    }
}
public class MyDerivedClass : MyBaseClass
{
    public
void DoSomething() { // Derived class implementation, hides base implementation. } }

儘管這段程式碼正常執行,但它會產生一個警告,說明隱藏了一個基類成員。如果是無意間隱藏
了一個需要使用的成員,此時就可以改正錯誤。如果確實要隱藏該成員, 就可以使用new 關鍵字顯式地表明意圖

public class MyDerivedClass : MyBaseClass
{
    new public void DoSomething()
    {
        // Derived class implementation, hides base implementation.
} }

其工作方式是完全相同的,但不會顯示警告。此時應注意隱藏基類成員和重寫它們的區別。考
慮下面的程式碼:

public class MyBaseClass
{
    public virtual void DoSomething()
    {
        Console.WriteLine("Base imp");
    }
}
public class MyDerivedClass : MyBaseClass
{
    public override void DoSomething()
    {
        Console.WriteLine("Derived imp"
); } }

其中重寫方法將替換基類中的實現程式碼,這樣,下面的程式碼就將使用新版本,即使這是通過基
類型別進行的,情況也是這樣(使用多型性):

MyDerivedClass myObj = new MyDerivedClass();
MyBaseClass myBaseObj;
myBaseObj = myObj;
myBaseObj.DoSomething();

結果如下:

Derived imp

另外,還可以使用下面的程式碼隱藏基類方法:

public class MyBaseClass
{
    public virtual void DoSomething()
    {
        Console.WriteLine("Base imp");
    }
}
public class MyDerivedClass : MyBaseClass
{
    new public void DoSomething()
    {
        Console.WriteLine("Derived imp");
    }
}

基類方法不必是虛擬的,但結果是一樣的,只需修改上面程式碼中的一行即可。對於基類的虛擬
方法和非虛擬方法來說, 其結果如下:

Base imp

儘管隱藏了基類的實現程式碼,但仍可以通過基類訪問它。

呼叫重寫或隱藏的基類方法

無論是重寫成員還是隱藏成員,都可以在派生類的內部訪問基類成員。這在許多情況下都是很
有用的,例如:

  1. 要對派生類的使用者隱藏繼承的公共成員,但仍能在類中訪問其功能。
  2. 要給繼承的虛擬成員新增實現程式碼,而不是簡單地用重寫的新執行程式碼替換它。

為此,可以使用base 關鍵字,它表示包含在派生類中的基類的實現程式碼,例如:

public class MyBaseClass
{
    public virtual void DoSomething()
    {
        // Base implementation.
    }
}
public class MyDerivedClass : MyBaseClass
{
    public override void DoSomething()
    {
        // Derived class implementation, extends base class implementation.
        base.DoSomething();
        // More derived class implementation.
    }
}

這段程式碼執行包含在MyBaseClass 中的DoSomething()版本,MyBaseClass 是MyDerivedClass
的基類,而DoSomething()版本包含在MyDerivedClass 中。因為base 使用的是物件例項,所以在靜
態成員中使用它會產生錯誤。

this 關鍵字

除了使用第9 章的base 關鍵字外,還可以使用this 關鍵字。與base 一樣,this 也可以用在類成
員的內部,且該關鍵字也引用物件例項。只是this 引用的是當前的物件例項(即不能在靜態成員中使
用this 關鍵字,因為靜態成員不是物件例項的一部分)。
this 關鍵字最常用的功能是把當前物件例項的引用傳遞給一個方法,如下例所示:

public void doSomething()
{
    MyTargetClass myObj = new MyTargetClass();
    myObj.DoSomethingWith(this);
}

其中,被例項化的MyTargetClass 例項有一個DoSomethingWith()方法,該方法帶有一個引數,其型別與包含上述方法的類相容。這個引數型別可以是類的型別、由這個類繼承的類型別,或者由
這個類或System.Object 實現的一個介面。
this 關鍵字的另一個常見用法是限定本地型別的成員,例如:

public class MyClass
{
    private int someData;
    public int SomeData
    {
        get
        {
            return this.someData;
        }
    }
}

許多開發人員都喜歡這個語法,它可以用於任意成員型別,因為可以一眼看出引用的是成員,
而不是區域性變數。

巢狀的型別定義

除了在名稱空間中定義型別之外,還可以在其他類中定義這些類。如果這麼做,就可以在定義
中使用各種訪問修飾符,而不僅僅是public 和internal,也可以使用new 關鍵字隱藏繼承於基類的類
型定義。例如,下面的程式碼定義了MyClass,也定義了一個巢狀的類MyNestedClass:

public class MyClass
{
    public class MyNestedClass
    {
        public int NestedClassField;
    }
}

如果要在MyClass 的外部例項化MyNestedClass,就必須限定名稱,例如:

MyClass.MyNestedClass myObj = new MyClass.MyNestedClass();

但是,如果巢狀的類宣告為私有,或者宣告為其他與執行該例項化的程式碼不相容的訪問級別,
就不能這麼做。這個功能主要用於定義對於其包含類來說是私有的類,這樣,名稱空間中的其他代
碼就不能訪問它。

節選自《C# 入門經典》第五版