接口
前言:如果一个类派生自一个类,声明这个类就会实现某些函数。并不是所有的面向对象的语言都支持接口。首先我们先声明一个接口:
public interface IDisposable { void Dispose(); }
上面的代码说明:声明接口在语法上与声明抽象类是完全相同的。但是不允许提供接口中任何成员的实现方式。一般情况下,接口只能包含方法、属性、索引器和事件的声明,不能实例化接口,它只能包含其成员的签名。接口既不能有构造函数也不能有字段。接口定义也不允许运算符的重载。在接口的定义中还不允许声明关于成员的修饰符,而是因为接口通常总是共有的,不能声明为虚拟或者是静态的。
public class SomeClass : IDisposable { public void Dispose() { } }
如果SameClasss派生于IDisposable类,但不包含IDisposable类中签名相同的Dispose()方法,就会得到一个编译的错误。IDisposable是一个相当简单的接口,它只定义了一个方法,大多数接口都包含许多的成员。
1:定义和实现接口:
下面我们遵循接口继承规范的小例子来说明如何定义和使用接口的。表示银行账户的所有类都实现接口IBankAccount。该接口包含一个用于存取款的方法和一个返回余额的属性。这个接口还允许外部的代码识别有不同银行账户实现的各种银行账户类。首先我们先定义IBankAccount接口:
interface IBankAccount { /// <summary> /// 付款 /// </summary> /// <param name="amount"></param> void PayIn(decimal amount); /// <summary> /// 提款 /// </summary> /// <param name="amount"></param> /// <returns></returns> bool Withdraw(decimal amount); /// <summary> /// 返回余额的属性 /// </summary> decimal Balance { get; } }
现在我们可以编写银行账户的类了。这些类之间不必彼此相关。它们可以是完全不同的类。但它们都表示银行账户,因为它们都实现了IBankAccount接口。我们定义一个RoyalBankOfVenus运行的存款账户。
public class RoyalBankOfVenus : IBankAccount { private decimal _balance; /// <summary> /// 用户的余额 /// </summary> public decimal Balance { get { return _balance; } } /// <summary> /// 存储金额 /// </summary> /// <param name="amount"></param> public void PayIn(decimal amount) { _balance += amount; } /// <summary> /// 余额的判断 /// </summary> /// <param name="amount"></param> /// <returns></returns> public bool Withdraw(decimal amount) { if (this.Balance >= amount) { _balance -= amount; return true; } Console.WriteLine("你的余额不足"); return false; } }
当我们的类继承与接口的时候,必须实现这些方法的所有的实现的代码。如果缺少实现代码,编译器就会产生错误。接口仅表示其成员的存在性,类负责确定这些成员时虚拟的还是抽象的(但只有类的本身是抽象的,这些函数才是抽象的)。在本例中,接口的任何函数不必是虚拟的。有了自己的类后我们就可以在Main方法中进行调用了:
static void Main(string[] args) { //存款的账户 IBankAccount bankAccount = new RoyalBankOfVenus(); //存款 bankAccount.PayIn(200); //提款 bankAccount.Withdraw(100); Console.WriteLine("卡上的余额是:{0}", bankAccount.Balance); Console.ReadKey(); }
接口引用完全可以看成类引用:但是接口的强大之处在于:它可以引用任何实现该接口的类。例如:我们可以构造接口数组,其中数组的每个元素都是不同的类:
static void Main(string[] args) { IBankAccount[] accounts = new IBankAccount[2]; accounts[0] = new RoyalBankOfVenus(); accounts[1] = new RoyalBankOfVenus2(); }
2.派生的接口:
接口之间可以相互的继承,其方式与类的继承的方式相同。我们下面来定义一个新的接口ITransferBankAccount来说明这个概念。该接口的功能和IBankAccount相同。只是又定义了一个方法,把资金直接转到另一个账户上。
public interface ITransferBankAccount : IBankAccount { bool TransferTo(IBankAccount destination, decimal amount); }
因为ITransferBankAccount派生自IBankAccount,所以他拥有IBankAccount的所有成员和它自己的成员。这表示实现(派生自)ITransferBankAccount的任何类都必须实现IBankAccount的所有的方法和在ITransferBankAccount中定义的新的方法TransferTo(),没有实现所有方法就会产生一个编译的错误。
public class RoyalBankOfVenus : ITransferBankAccount { private decimal _balance; /// <summary> /// 用户的余额 /// </summary> public decimal Balance { get { return _balance; } } /// <summary> /// 存储金额 /// </summary> /// <param name="amount"></param> public void PayIn(decimal amount) { _balance += amount; } /// <summary> /// 存入另一个账户中 /// </summary> /// <param name="destination"></param> /// <param name="amount"></param> /// <returns></returns> public bool TransferTo(IBankAccount destination, decimal amount) { bool result = Withdraw(100); //先取钱 if (result) { destination.PayIn(amount); } return result; } /// <summary> /// 取款的判断 /// </summary> /// <param name="amount"></param> /// <returns></returns> public bool Withdraw(decimal amount) { if (this.Balance >= amount) { _balance -= amount; return true; } Console.WriteLine("你的余额不足"); return false; } }
客户端的调用:
static void Main(string[] args) { //存款的账户 IBankAccount bankAccount = new RoyalBankOfVenus(); //另一个的存款的账户 ITransferBankAccount transferBankAccount = new CurrentAccount(); //存款 bankAccount.PayIn(200); //提款 transferBankAccount.PayIn(500); //存到另一个账户上 transferBankAccount.TransferTo(bankAccount, 100); Console.WriteLine("卡上的余额是:{0}", bankAccount.Balance); Console.WriteLine("另一个账户上的余额是:{0}", transferBankAccount.Balance); Console.ReadKey(); }