多繼承
如果要使用多繼承,需要使用接口,因為C#中的類只支持單繼承,而接口支持多繼承,實現多繼承時,繼承的多個接口中間用逗號(,)隔開。
說明:
實現多繼承時,繼承的可以是多個接口,也可以是一個類及多個接口。
下面通過一個實例講解如何實現多繼承。
例創建一個控制台應用程序,首先定義兩個接口,分別表示人的實體接口和行為接口;然后聲明一個類,並使這個類繼承於定義的兩個接口,在該類中實現接口中的成員屬性和方法;最后在Main方法中實例化派生類的對象,並使用該派生類對象調用人的實體接口和行為接口中的屬性和方法。代碼如下:
interface IPeopleEntity //定義一個實體接口
{
string Name //定義名字屬性
{
get;
set;
}
}
interface IPeopleActive //定義一個行為接口
{
void say(string str); //定義說話方法
}
class PeopleClass:IPeopleEntity,IPeopleActive //繼承定義的兩個接口
{
string name = ""; //定義名字變量
public string Name //實現接口中定義的名字屬性
{
get
{
return name;
}
set
{
name = value;
}
}
bool CheckChinese(string str) //定義一個方法,用來判斷字符串是不是中文
{
bool flag = false; //定義一個bool類型變量,作為標識
UnicodeEncoding encode = new UnicodeEncoding(); //實例化編碼對象
byte[] b = encode.GetBytes(str); //將字符串轉換為字節數組
for (int i = 0; i < b.Length; i++) //遍歷字節數組
{
if (b[i] != 0) //判斷字節數組中指定索引處的值是不是0
{
flag = true; //設置標識為true
}
else
{
flag = false; //設置標識為false
}
}
return flag; //返回定義的標識
}
public void say(string str) //實現接口中定義的說話方法
{
if (CheckChinese(str)) //判斷輸入的是不是中文
{
Console.WriteLine(str+"是中國人,請說漢語!");
}
else
{
Console.WriteLine(str + " is a american,please speak english!");
}
}
}
class Program
{
static void Main(string[] args)
{
PeopleClass peopleclass = new PeopleClass(); //實例化類對象
while (true)
{
Console.Write("請輸入名字:");
peopleclass.Name = Console.ReadLine(); //記錄用戶輸入的名字
peopleclass.say(peopleclass.Name); //根據用戶輸入顯示相應的字符串
}
}
}
繼承的原則
上面詳細講解了如何實現繼承,包括單繼承和多繼承,這里主要總結一下C#中實現繼承的幾個主要原則,分別如下:
q除了object類,每個類有且只有一個直接基類,如果沒有顯式指定類的直接基類,那么它的直接基類就隱含的設置為object。object類沒有任何直接或間接基類,它是所有類的終極基類;
q無論基類成員的可訪問性如何,除構造函數和析構函數外,所有其他基類的成員都能被子類繼承,然而,有些繼承成員在子類中可能是不可訪問的,比如,基類的private成員在子類中不可訪問,但是,如果將子類的對象作為參數傳入基類的方法內,那么在基類的代碼內部,就可以通過子類或者子類的對象來訪問基類的private成員;
q子類可以擴展它的直接基類;
q繼承是可以傳遞的,比如C類從B類繼承,而B類從A類繼承,那么C類就會既繼承B類中的成員,又繼承A類中的成員;
q類不能循環繼承,比如A類繼承於B類,而B類繼承於C類,那么C類就不能再去繼承A類,因為它們之間存在了一種循環關系;
q類的直接基類必須至少與類本身具有同樣的可訪問性,比如,如果從private類派生一個public類,將會導致編譯時錯誤;
q在子類中可以聲明具有相同名稱或簽名的新成員來隱藏從基類繼承而來的成員,但是,隱藏繼承而來的成員時並不移除該成員,而只是使被隱藏的成員在子類中不可以直接訪問;
q類中可以聲明虛方法等,而子類可以重寫這些虛方法的實現;
qC#中只支持類的單一繼承,但是支持接口的多重繼承;
q類的實例包含在該類中及它的所有基類中聲明的所有實例字段的集合,並且存在一個從子類到它的任何基類的隱式轉換,因此,可以將子類的實例看成是其任何基類的實例的引用。
.net筆試題
答:C# 中的接口與類不同,可以使用多繼承,即一個子接口可以有多個父接口。但如果兩個父成員具有同名的成員,就產生了二義性,這時在實現時最好使用顯式的聲明
示例:
using System;
using System.Collections.Generic;
using System.Text;
namespace Example17
{
class program
{
//一個完整的接口聲明示例
interface IExample
{
//屬性
string p
{
get;
set;
}
//方法
string F(int Value);
//事件
event EventHandler E;
//索引指示器
string this[int Index]
{
get;
set;
}
}
interface IA
{
int Count { get; set;}
}
interface IB
{
int Count();
}
//IC接口從IA和IB多重繼承
interface IC : IA, IB
{
}
class C : IC
{
private int count = 100;
//顯式聲明實現IA接口中的Count屬性
int IA.Count
{
get { return 100; }
set { count = value; }
}
//顯式聲明實現IB接口中的Count方法
int IB.Count()
{
return count * count;
}
}
static void Main(string[] args)
{
C tmpObj = new C();
//調用時也要顯式轉換
Console.WriteLine("Count property: {0}", ((IA)tmpObj).Count);
Console.WriteLine("Count function: {0}", ((IB)tmpObj).Count());
Console.ReadLine();
}
}
}
結果:
Count property: 100
Count function: 10000