重寫,隱藏,抽象,多型

iDotNetSpace發表於2008-09-23
  • virtual 用在基類中,指定一個虛方法(屬性),表示這個方法(屬性)可以重寫。
  • override 用在派生類中,表示對基類虛方法(屬性)的重寫。

以上的基類和派生類都是相對的。B 是 C 的基類,也可以是 A 的派生類,B 中既可以對 A 中的 virtual 虛方法用 override 重寫,也可以指定 virtual 虛方法供 C 重寫。

  • 不能重寫非虛方法或靜態方法。重寫的基方法必須是 virtual、abstract 或 override 的。為什麼 override 也可以重寫呢?因為基類中的 override 實際上是對基類的基類進行的重寫,由於繼承可傳遞,所以也可以對基類中 override 的方法進行重寫。
  • override 宣告不能更改 virtual 方法的可訪問性。override 方法和 virtual 方法必須具有相同的訪問級別修飾符。
  • 不能使用修飾符 new、static、virtual 或 abstract 來修改 override 方法。
  • 重寫屬性宣告必須指定與繼承屬性完全相同的訪問修飾符、型別和名稱,並且被重寫的屬性必須是 virtual、abstract 或 override 的。
public class BaseClass
{
public virtual string GetString()
{
return "這是一個虛方法。";
}
}
public class DerivedClass : BaseClass
{
public override string GetString()
{
return "這是重寫了的方法。";
}
}
 
 

public class BaseClass
{
public string GetString()
{
return "這是基類的一個方法。";
}
}
public class DerivedClass : BaseClass
{
public new string GetString()
{
return "這是隱藏了基類 GetString() 的方法。";
}
}

可以看出隱藏使用的是關鍵字 new

 

 

 

我們在分析問題時,越往上分析,就感覺結構越抽象。比如,我們分析動物的捕獵行為:這幾種動物是群力合作,那幾種動物是耐心守候,那幾種動物是致命一擊……他們都有一個方法叫“捕獵”,只是我們無法給他們一個統一的過程。此時我們可以在他們的基類中定義一個抽象方法,該方法什麼事也不做,只是佔個名字。

public abstract class HuntingAnimal
{
public abstract void Hunt();
}
public class Tiger : HuntingAnimal
{
public override void Hunt()
{
//...
}
}

HuntingAnimal 用 abstract 定義了一個抽象方法 Hunt(),由於抽象方法不做什麼事情,所以不需要大括號,直接加引號結束即可。在派生類中,用 override 來實現這個抽象方法。

  • 抽象的類不能被例項化,所以不能用 new 來產生例項。
  • 如果方法是抽象的,則類必須是抽象的。
  • 派生類必須實現基類中的所有抽象方法,如果它不能做到,那麼它也應該是個抽象類。
  • 抽象類不能是密封的。(關於密封:如果我們不想讓一個類被繼承,可以使用 sealed 關鍵字來確保它不會被繼承。)

注意,雖然虛方法和抽象方法均是利用 override 關鍵字來重寫,但虛方法和抽象方法是完全不同的。

 

 

一般我們指的多型性是指“執行時的多型性”,也就是在程式執行時,系統根據不同的物件確定呼叫物件所屬類的相應方法的能力。

示例

namespace Cftea
{
public class BaseClass
{
public virtual string GetStringVirtual()
{
return "基類虛方法。";
}
public string GetString()
{
return "基類方法。";
}
}
public class DerivedClass : BaseClass
{
public override string GetStringVirtual()
{
return "派生類重寫方法。";
}
public new string GetString()
{
return "派生類隱藏方法。";
}
}
public partial class Form1 : Form.
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClass = derivedClass;
MessageBox.Show("derivedClass.GetStringVirtual() 結果是:" + derivedClass.GetStringVirtual() +
"\r\n" +
"baseClass.GetStringVirtual() 結果是:" + baseClass.GetStringVirtual() + "\r\n" +
"derivedClass.GetString() 結果是:" + derivedClass.GetString() + "\r\n" +
"baseClass.GetString() 結果是:" + baseClass.GetString());
}
}
}

執行結果是:

c-sharp多型性演示結果

我們可以看到,derivedClass 與 baseClass 型別不同,但是指向的都是 new DerivedClass():

  • 他們在呼叫 GetStringVirtual() 時,使用的都是派生類的。(多型性)
  • 他們在呼叫 GetString() 時,使用的是各自型別所在的方法。

從這裡我們可以看出重寫與隱藏的區別了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-462661/,如需轉載,請註明出處,否則將追究法律責任。

相關文章