C#中的接口与Java类似,略有不同。
1. 接口的定义
C#中接口可以包含一个或多个成员,这些成员可以是方法、属性、索引指示器和事件,但不能是常量、域操作符、构造函数或析构函数,而且不能包含任何静态成员。
接口成员默认访问方式是public,接口成员声明不能包含任何修饰符,比如成员声明前不能加abstract, public, protected, internal, private, virtual, override 或static 修饰符。
给一个接口的定义实例:
 
interface IExample
{
//注意: 与Java不同的是,C#中接口声明不能添加任何修饰符,默认是public
//定义方法
void F(int value);
//定义属性
string P { get; set; }
//定义索引指示器
string this[int index] { get; set; }
//定义事件
event EventHandler E;
}
2. 对接口成员的访问
由于接口是支持多继承的,在多继承中,如果两个父接口都包含了同名的成员,这就会产生二义性,这时需要进行显式的声明。
如下面的实例:
 
using System;
interface IInteger
{
void Add(int i);
}
interface IDouble
{
void Add(double d);
}
interface INumber : IInteger, IDouble { }
class C
{
void Test(INumber n)
{
//n.Add(1); 错误
((IInteger)n).Add(1); // 正确
((IDouble)n).Add(1); // 正确
}
}
/*
* 调用n.Add(1) 会导致二义性,因为候选的重载方法的参数类型均适用.
* 只要加入了显式的指派就决不会产生二义性
*/
接口的多继承也带来了一定的问题,这里主要是使用new覆盖的问题,例如下面的示例:
 
interface IBase
{
void F(int i);
}
interface ILeft : IBase
{
new void F(int i);
}
interface IRight : IBase
{
void G();
}
interface IDerived : ILeft, IRight { }
class A
{
void Test(IDerived d)
{
d.F(1); // 调用 ILeft.F
((IBase)d).F(1); // 调用 IBase.F
((ILeft)d).F(1); // 调用 ILeft.F
((IRight)d).F(1); // 调用 IBase.F
}
}
/*
* 方法IBase.F 在派生的接口ILeft 中被 Ileft 的成员方法F 覆盖了,所以对 d.F(1) 的调用实际上调用了ILeft.F.
* 虽然从IBase IRight IDerived 这条继承路径上来看, ILeft.F 方法是没有被覆盖的
* 我们只要记住这一点: 一旦成员被覆盖以后,所有对其的访问都被覆盖以后的成员拦截了
*/
3. 接口的实现
接口的实现是在类或者结构中,主要是在类中。 这部分与Java类似,不同的部分见下面示例描述:
3.1 显式接口成员
 
using System;
interface IControl
{
void Paint();
}
interface IDataBound
{
void Bind(Binder b);
}
public class Control: IControl
{
public void Paint()
{
//do somethings
}
}
public class EditBox: Control, IControl, IDataBound
{
public void Paint()
{
// do somethings
}
public void Bind(Binder b)
{
//do somethings
}
}
/*
* 类EditBox 从Control 类继承并同时实现了IControl 和 IDataBound 接口
* EditBox 中的Paint 方法来自IControl 接口,Bind 方法来自 IDataBound 接口
* 二者在 EditBox 类中都作为公有成员实现, 当然在C# 中我们也可以选择不作为公有成员实现接口
* 如果每个成员都明显地指出了被实现的接口,通过这种途径被实现的接口,我们称之为显式接口成员explicit interface member
*/
显式接口成员的特点是:只能被接口调用,例如如下示例:
 
public class EditBox: IControl, IDataBound
{
void IControl.Paint()
{
//do somethings
}
void IDataBound.Bind(Binder b)
{
//do somethings
}
}
class Test
{
static void Main()
{
EditBox editbox = new EditBox();
editbox.Paint(); // error: no such method
IControl control = editbox;
control.Paint(); // calls EditBox’s Paint implementation
}
}
/*
* 上述代码中对editbox.Paint()的调用是错误的,因为editbox 本身并没有提供这一方法.
* control.Paint()才是正确的调用方式
*/
3.2 接口的映射
类必须为在声明中列出的所有接口成员提供具体的实现。在类中定位接口成员的实现称之为接口映射(interface mapping)。
相关示例如下:
 
interface IControl
{
void Paint();
}
class Control: IControl
{
public void Paint()
{
//do somethings
}
}
class TextBox: Control
{
new public void Paint()
{
//do somethings
}
}
/*
* TextBox 中的Paint 方法覆盖了Control 中的Paint 方法,但却没有改变Control.Paint 对 IControl.Paint 的映射
* 在类的实例和接口的实例中对Paint方法的调用会产生下面这样的结果:
* Control c = new Control();
* TextBox t = new TextBox();
* IControl ic = c;
* IControl it = t;
* c.Paint(); // invokes Control.Paint();
* t.Paint(); // invokes TextBox.Paint();
* ic.Paint(); // invokes Control.Paint();
* it.Paint(); // invokes Control.Paint();
* 如果需要让it去调用TextBox.Paint(),就要用virtual方法去实现Control中的Paint,然后再TextBox中new一个Paint()
*/
3.3 接口的重实现(也就是重映射)
所谓接口的重实现,其实就是接口的重映射。示例如下:
 
interface IControl
{
void Paint();
}
class Control: IControl
{
void IControl.Paint()
{
//do somethings
}
}
class MyControl: Control, IControl
{
public void Paint() {}
}
/*
* Control 把IControl.Paint 映射到了Control.IControl.Paint 上,
* 但这并不影响在MyControl 中的重实现(重映射)
* 在MyControl 中的重实现中,IControl.Paint 被映射到MyControl.Paint 之上
*/
3.4 抽象类与接口
其实接口就是一种纯的抽象类,与接口不同的是:抽象类可以继承接口,把接口映射到抽象函数。示例如下:
interface IMethods
{
void F();
void G();
}
abstract class C : IMethods
{
//这里将IMethods的F()和G()映射到了类C的抽象方法上
public abstract void F();
public abstract void G();
}
          
常遇困境,说明你在进步! 
      
常有压力,说明你有目标! 
作者:notifier
    
出处:http://www.cnblogs.com/notifier/ 
   本文版权归作者notifier和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利!   
       
 
                    
                     
                    
                 
                    
                 
 
        
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号