基本概念
如果一个类派生自一个接口,声明这个类就会实现某些函数。
public interface IDisposable
{
void Dispose();
}
比较接口和抽象类:
抽象类可以有实现代码或没有实现代码的抽象成员。
接口不能有任何实现代码;它是纯粹抽象的。
因为接口的成员总是抽象的,所以接口不需要abstract关键字。
:::danger
接口既不能有构造函数也不能有字段。如果缺少实现代码,编译器就会产生错误。
接口仅表示其成员的存在性,类负责确定这些成员是虚拟还是抽象的(但只有在类本身是抽象的,这些函数才能是抽象的)。
:::
class SomeClass: IDisposable
{
// This class MUST contain an implementation of the
// IDisposable.Dispose() method, otherwise
// you get a compilation error.
public void Dispose()
{
// implementation of Dispose() method
}
// rest of class
}
:::danger 继承接口,必须要实现接口中定义的方法。 :::
实例
建立在银行账户的基础上。
假定编写代码,最终允许在银行账户之间进行计算机转账业务。
许多公司可以实现银行账户,但它们一致认为,表示银行账户的所有类都实现接口IBankAccount。
该接口包含一个用于存取款的方法和一个返回余额的属性。
这个接口还允许外部代码识别由不同银行账户实现的各种银行账户类。
定义IBankAccount接口
namespace Wrox.ProCSharp
{
public interface IBankAccount
{
void PayIn(decimal amount);
bool Withdraw(decimal amount);
decimal Balance { get; }
}
}
接口名称通常以字母I开头,以便知道这是一个接口。
:::info 在名称的前面加一个字母,表示所定义对象的类型。 :::
继承接口
下面是第一个类,一个由Royal Bank of Venus运行的存款账户
namespace Wrox.ProCSharp.VenusBank
{
public class SaverAccount: IBankAccount
{
private decimal _balance;
public void PayIn(decimal amount) => _balance += amount;
public bool Withdraw(decimal amount)
{
if (_balance >= amount)
{
_balance -= amount;
return true;
}
WriteLine("Withdrawal attempt failed.");
return false;
}
public decimal Balance => _balance;
public override string ToString() => $"Venus Bank Saver: Balance = {_balance,6:C}";
}
}
不同的类如何实现相同的接口
下面假定Planetary Bank of Jupiter还实现一个类GoldAccount来表示其银行账户中的一个
namespace Wrox.ProCSharp.JupiterBank
{
public class GoldAccount: IBankAccount
{
// etc
}
}
//这里没有列出GoldAccount类的细节,因为在本例中它基本上与SaverAccount的实现代码相同。
派生的接口
接口可以彼此继承,其方式与类的继承方式相同。
namespace Wrox.ProCSharp
{
public interface ITransferBankAccount: IBankAccount
{
bool TransferTo(IBankAccount destination, decimal amount);
}
}
ITransferBankAccount派生自IBankAccount,所以它拥有IBankAccount的所有成员和它自己的成员。