从技术上讲接口是一组包含了函数型方法的数据结构通过这组数据结构客户代码可以调用组件对象的功能
定义接口成员
接口可以包含一个和多个成员这些成员可以是方法属性索引指示器和事件但不能是常量域操作符构造函数或析构函数而且不能包含任何静态成员接口定义创建新的定义空间并且接口定义直接包含的接口成员定义将新成员引入该定义空间
说明
· 接口的成员是从基接口继承的成员和由接口本身定义的成员
· 接口定义可以定义零个或多个成员接口的成员必须是方法属性事件或索引器接口不能包含常数字段运算符实例构造函数析构函数或类型也不能包含任何种类的静态成员
· 定义一个接口该接口对于每种可能种类的成员都包含一个方法属性事件和索引器
· 接口成员默认访问方式是public接口成员定义不能包含任何修饰符比如成员定义前不能加abstractpublicprotectedinternalprivatevirtualoverride 或static 修饰符
· 接口的成员之间不能相互同名继承而来的成员不用再定义但接口可以定义与继承而来的成员同名的成员这时我们说接口成员覆盖了继承而来的成员这不会导致错误但编译器会给出一个警告关闭警告提示的方式是在成员定义前加上一个new关键字但如果没有覆盖父接口中的成员使用new关键字会导致编译器发出警告
· 方法的名称必须与同一接口中定义的所有属性和事件的名称不同此外方法的签名必须与同一接口中定义的所有其他方法的签名不同
· 属性或事件的名称必须与同一接口中定义的所有其他成员的名称不同
· 一个索引器的签名必须区别于在同一接口中定义的其他所有索引器的签名
· 接口方法声明中的属性(attributes) 返回类型(returntype) 标识符(identifier)和形式参数列表(formalparameterlis)与一个类的方法声明中的那些有相同的意义一个接口方法声明不允许指定一个方法主体而声明通常用一个分号结束
· 接口属性声明的访问符与类属性声明的访问符相对应除了访问符主体通常必须用分号因此无论属性是读写只读或只写访问符都完全确定
· 接口索引声明中的属性(attributes)类型(type)和形式参数列表(formalparameterlist)与类的索引声明的那些有相同的意义
下面例子中接口IMyTest包含了索引指示器事件E方法F属性P这些成员
interface IMyTest{
string this[int index] { get; set; }
event EventHandler E ;
void F(int value) ;
string P { get; set; }
}
public delegate void EventHandler(object sender EventArgs e) ;
下面例子中接口IStringList包含每个可能类型成员的接口一个方法一个属性一个事件和一个索引
public delegate void StringListEvent(IStringList sender);
public interface IStringList
{
void Add(string s);
int Count { get; }
event StringListEvent Changed;
string this[int index] { get; set; }
}
接口成员的全权名
使用接口成员也可采用全权名(fully qualified name)接口的全权名称是这样构成的接口名加小圆点 再跟成员名比如对于下面两个接口
interface IControl {
void Paint( ) ;
}
interface ITextBox: IControl {
void GetText(string text) ;
}
其中Paint 的全权名是IControlPaintGetText的全权名是ITextBox GetText当然全权名中的成员名称必须是在接口中已经定义过的比如使用ITextBoxPaint就是不合理的
如果接口是名字空间的成员全权名还必须包含名字空间的名称
namespace System
{
public interface IDataTable {
object Clone( ) ;
}
}
那么Clone方法的全权名是System IDataTableClone
定义好了接口接下来我们关心的就是怎样实现对接口的访问这部分内容我将在下一篇文章中和您进一步探讨
定义接口的一般形式为
[attributes] [modifiers] interface identifier [:baselist] {interfacebody}[;]
说明
· attributes(可选)附加的定义性信息
· modifiers(可选)允许使用的修饰符有new和四个访问修饰符分别是newpublicprotectedinternalprivate在一个接口定义中同一修饰符不允许出现多次new修饰符只能出现在嵌套接口中
表示覆盖了继承而来的同名成员The public protected internal and private修饰符定义了对接口的访问权限
· 指示器和事件
· identifier接口名称
· baselist(可选):包含一个或多个显式基接口的列表接口间由逗号分隔
· interfacebody对接口成员的定义
· 接口可以是命名空间或类的成员并且可以包含下列成员的签名 方法属性索引器
· 一个接口可从一个或多个基接口继承
接口这个概念在C#和Java中非常相似接口的关键词是interface一个接口可以扩展一个或者多个其他接口按照惯例接口的名字以大写字母I开头下面的代码是C#接口的一个例子它与Java中的接口完全一样
interface IShape {
void Draw ( ) ;
}
如果你从两个或者两个以上的接口派生父接口的名字列表用逗号分隔如下面的代码所示
interface INewInterface: IParent IParent { }
然而与Java不同C#中的接口不能包含域(Field)另外还要注意在C#中接口内的所有方法默认都是公用方法在Java中方法定义可以带有public修饰符(即使这并非必要)但在C#中显式为接口的方法指定public修饰符是非法的例如下面的C#接口将产生一个编译错误
interface IShape { public void Draw( ) ; }
下面的例子定义了一个名为IControl 的接口接口中包含一个成员方法Paint
interface IControl {
void Paint( ) ;
}
在下例中接口 IInterface从两个基接口 IBase 和 IBase 继承
interface IInterface: IBase IBase {
void Method( ) ;
void Method( ) ;
}
接口可由类实现实现的接口的标识符出现在类的基列表中例如
class Class: Iface Iface {
// class 成员
}
类的基列表同时包含基类和接口时列表中首先出现的是基类例如
class ClassA: BaseClass Iface Iface {
// class成员
}
以下的代码段定义接口IFace它只有一个方法
interface IFace {
void ShowMyFace( ) ;
}
不能从这个定义实例化一个对象但可以从它派生一个类因此该类必须实现ShowMyFace抽象方法
class CFace:IFace
{
public void ShowMyFace( ) {
ConsoleWriteLine( implementation ) ;
}
}
基接口
一个接口可以从零或多个接口继承那些被称为这个接口的显式基接口当一个接口有比零多的显式基接口时那么在接口的定义中的形式为接口标识符后面跟着由一个冒号:和一个用逗号分开的基接口标识符列表
接口基
接口类型列表说明
· 一个接口的显式基接口必须至少同接口本身一样可访问例如在一个公共接口的基接口中指定一个私有或内部的接口是错误的
· 一个接口直接或间接地从它自己继承是错误的
· 接口的基接口都是显式基接口并且是它们的基接口换句话说基接口的集合完全由显式基接口和它们的显式基接口等等组成在下面的例子中
interface IControl {
void Paint( ) ;
}
interface ITextBox: IControl {
void SetText(string text) ;
}
interface IListBox: IControl {
void SetItems(string[] items) ;
}
interface IComboBox: ITextBox IListBox { }
IComboBox 的基接口是IControl ITextBox 和 IlistBox
· 一个接口继承它的基接口的所有成员换句话说上面的接口IComboBox就像Paint一样继承成
员SetText 和 SetItems
· 一个实现了接口的类或结构也隐含地实现了所有接口的基接口
接口主体
一个接口的接口主体定义接口的成员
interfacebody:
{ interfacememberdeclarationsopt }