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
儘管隱藏了基類的實現程式碼,但仍可以通過基類訪問它。
呼叫重寫或隱藏的基類方法
無論是重寫成員還是隱藏成員,都可以在派生類的內部訪問基類成員。這在許多情況下都是很
有用的,例如:
- 要對派生類的使用者隱藏繼承的公共成員,但仍能在類中訪問其功能。
- 要給繼承的虛擬成員新增實現程式碼,而不是簡單地用重寫的新執行程式碼替換它。
為此,可以使用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# 入門經典》第五版