C#編程(二十五)----------接口
接口
如果一個類派生自一個接口,聲明這個類就會實現某些函數.並不是所有的面向對象的語言都支持接口.
例如,有一個接口:IDispoable,包含一個方法Dispose(),該方法又類實現,用於清理代碼:
public interface IDisposable
{
void Dispose();
}
上述代碼說明,聲明接口在語法上與聲明抽象類完全相同,但不允許提供接口中任何成員的實現方式.一般情況下,接口只能包含方法,屬性,索引器和事件的聲明.
不能實例化接口,他只能包含mount成員的二千名.接口既不能有構造函數,也不能有字段.接口定義也不允許包含運算符重載.
在接口定義中還不允許聲明關於成員的修飾符.接口成員總是共有的,不能聲明為虛擬或靜態.如果需要,就有實現的類來聲明,因此最好實現執行的類來聲明訪問修飾符.
例如上面的IDisposable接口中的Disposable方法.
class SomeClass : IDisposable
{
public void Disposable()
{
}
}
在這個例子中,如果SomeClass派生自IDisposable類,但沒有實現Disposable(),就會得到一個編譯錯誤,因為該類破壞了實現的IDisposable的一致協定.當然,編譯器允許類有一個不派生自IDisposable類的Disposable()方法.問題是其他代碼無法識別出SomeClass類支持的IDisposable特性.
定義和實現接口
下面開發一個遵循接口繼承規範的小例子說明如何定義和實現接口.編寫代碼,最終允許在銀行賬戶之間進行計算機轉賬業務.許多公司可以實現銀行賬戶,但他們都是彼此贊同表示銀行賬戶的所有類都實現接口IBankAccount.該接口包含一個用於存款的方法和一個返回余額的屬性.
我們的目的是允許銀行賬戶彼此通信,以便在賬戶之間進行轉賬業務.
首先定義接口:
public interface IBankAccount
{
void PayIn(decimal amount);
bool Withdraw(decimal amount);
decimal Balance
{
get;
}
}
註意接口的名稱為IBankAccount.接口的名稱通常是以字母I開頭,以便知道這是一個借口.
現在編寫表示銀行賬戶的類.這些類不必彼此相關,他們可以是完全不同的類.但他們都表示銀行賬戶,因為他們都實現了IBankAccount接口.
第一個類:
public class SavaAccount:IBankAccount
{
private decimal balance;
public void PayIn(decimal amount)
{
balance += amount;
}
public bool Withdraw(decimal amount)
{
if (balance>=amount)
{
balance -= amount;
return true;
}
Console.WriteLine("Withdrawal attempt failed. "); ;
return false;
}
public decimal Balance
{
get
{
return balance;
}
}
public override string ToString()
{
return string.Format("Venus Bank Saver : Balance ={0,6}:C",balance);
}
}
這個類包含了一個私有字段balance,當存款或取款時就調整這個字段.如果因為賬戶中的金額不足而取款失敗,就會顯示一條錯誤信息.
接下來看這個類的聲明:
public class SavaAccount : IBankAccount
SavaAccount 派生自一個接口IBankAccount,我們沒有明確指出任何其他積累.另外,從接口中派生完全獨立與類中派生.
SavaAccount 派生自IBankAccount,表示它獲得了IBankAccount的所有成員,但接口實際上並沒有實現其方法,所以SavaAccount 必須提供這些方法的所有實現代碼.如果缺少實現代碼,編譯器就會產生錯誤.
接口僅表示其成員的存在性,類負責確定這些成員是虛擬的還是抽象的(但只有在類本身是抽象的,這些函數才能是抽象)
另一個類:
public class GoldAccount : IBankAccount
{內容和SavaAccount類一樣}
然後再Main()方法中:
static void Main(string[] args)
{
IBankAccount venusAccount = new SvaAccount();
IBankAccount jupiterAccount = new GoldAccount();
venusAccount.PayIn(200);
venusAccount.Withdraw(100);
Console.WriteLine(venusAccount.ToString());
jupiterAccount.PayIn(500);
jupiterAccount.Withdraw(600);
jupiterAccount.Withdraw(100);
Console.WriteLine(jupiterAccount.ToString()); ;
Console.ReadKey();
}
輸出為:
Venus Bank Saver : Balance = 100$:
Withdrawal attempt failed.
jupit Bank Saver : Balance = 400$:
以上代碼中,要點是把兩個引用聲明變量為IBankAccount引用的方式.這表示他們可以指向實現這個借口的任何類的任何實例.但我們只能通過這些引用調用接口的一部分方法----如果要調用由類實現的但不在接口中的方法,就需要把引用強制轉換為合適的類型.我們調用了ToString(),但沒有進行任何顯示的強制轉換,這是因為ToString()是一個object方法,因此C#編譯器知道任何類都支持這個方法(換句話說,從人和接口到object的數據類型強制轉換為隱式的)
接口引用完全可以看做是類引用----但接口引用的強大之處在於,可以引用任何實現該接口的類.例如,我們可以構造接口數組,其中數組的每個元素都是不同的類:
IBankAccount[] accounts = new IBankAccount[2];
accounts[0] = new SvaAccount();
accounts[1] = new GoldAccount();
但是如果出現一個沒有繼承該接口的類就出現錯誤:
例如:
accounts[0] = new SomeClassAccount();這是錯誤的.
派生的接口
接口可以彼此派生,其方式與類的繼承方式相同.下面通過定義一個新的接口ITransferBankAccount來說明這個概念,該接口的功能與IBankAccount相同,只是定義了一個方法,把資金轉到另一個賬戶上.
定義該接口:
interface ITransferBankAccount:IBankAccount
{
bool TransferTo(IBankAccount destination, decimal amount);
}
因為ITransferBankAccount派生自IBankAccount,所以它擁有IBankAccount的所有成員和它自己的成員.這表示實現(派生自)ITransferBankAccount的任何類都必須實現IBankAccount的所有方法和在ITransferBankAccount中定義的新方法TransferTo().沒有實現這些所有的方法就會報錯.
註意TransferTo()方法對於目標賬戶使用了IBankAccount接口引用.這說明了接口的用途:在實現並調用這個方法是,不必知道轉賬的對象類型,只需要知道該對象實現了IBankAccount即可.
下面說明ITransferBankAccount:假定Jupiter還提供了一個當前賬戶.CurrentAccount類的大多數實現代碼與SvaAccount和GoldAccount的實現代碼相同.
public class CurrentAccount:ITransferBankAccount
{
private decimal balance;
public void PayIn(decimal amount)
{
balance += amount;
}
public bool Withdraw(decimal amount)
{
if (balance >= amount)
{
balance -= amount;
return true;
}
Console.WriteLine("Withdrawal attempt failed. "); ;
return false;
}
public decimal Balance
{
get
{
return balance;
}
}
public override string ToString()
{
return string.Format("jupit Bank Current Account : Balance ={0,6}$:", balance);
}
public bool TransferTo(IBankAccount destination, decimal amount)
{
bool result;
result = Withdraw(amount);
if (result)
{
destination.PayIn(amount);
}
return result;
}
}
Main()函數的內容:
IBankAccount venusAccount = new SvaAccount();
ITransferBankAccount jupiterAccount = new CurrentAccount();
venusAccount.PayIn(200);
jupiterAccount.PayIn(500);
jupiterAccount.TransferTo(venusAccount, 100);
Console.WriteLine(venusAccount.ToString());
Console.WriteLine(jupiterAccount.ToString());
Console.ReadKey();
輸出結果為:
Venus Bank Saver : Balance = 300$:
jupit Bank Current Account : Balance = 400$:
表示轉賬成功
C#編程(二十五)----------接口