类对接口的实现
前面我们已经说过,接口定义不包括方法的实现部分。接口可以通过类或结构来实现。我们主要讲述通过类来实现接口。用类来实现接口时,接口的名称必须包含在类定义中的基类列表中。
下面的例子给出了由类来实现接口的例子。其中ISequence 为一个队列接口,提供了向队列尾部添加对象的成员方法Add( ),IRing 为一个循环表接口,提供了向环中插入对象的方法Insert(object obj),方法返回插入的位置。类RingSquence 实现了接口ISequence 和接口IRing。
如果类实现了某个接口,类也隐式地继承了该接口的所有父接口,不管这些父接口有没有在类定义的基类表中列出。看下面的例子:
这里, 接口IcomboBox继承了ItextBox和IlistBox。类TextBox不仅实现了接口ITextBox,还实现了接口ITextBox 的父接口IControl。
前面我们已经看到,一个类可以实现多个接口。再看下面的例子:
类EditBox从类Control中派生并且实现了Icontrol和IdataBound。在前面的例子中接口Icontrol中的Paint方法和IdataBound接口中的Bind方法都用类EditBox中的公共成员实现。C#提供一种实现这些方法的可选择的途径,这样可以使执行这些的类避免把这些成员设定为公共的。接口成员可以用有效的名称来实现。例如,类EditBox可以改作方法Icontrol.Paint和IdataBound.Bind来来实现。
因为通过外部指派接口成员实现了每个成员,所以用这种方法实现的成员称为外部接口成员。外部接口成员可以只是通过接口来调用。例如,Paint方法中EditBox的实现可以只是通过创建Icontrol接口来调用。
上例中,类EditBox 从Control 类继承并同时实现了IControl and IDataBound 接口。EditBox 中的Paint 方法来自IControl 接口,Bind 方法来自IDataBound 接口,二者在EditBox 类中都作为公有成员实现。当然,在C# 中我们也可以选择不作为公有成员实现接口。
如果每个成员都明显地指出了被实现的接口,通过这种途径被实现的接口我们称之为显式接口成员(explicit interface member)。 用这种方式我们改写上面的例子:
显式接口成员只能通过接口调用。例如:
上述代码中对editbox.Paint( )的调用是错误的,因为editbox 本身并没有提供这一方法。control.Paint( )是正确的调用方式。
注释:接口本身不提供所定义的成员的实现,它仅仅说明这些成员,这些成员必须依靠实现接口的类或其它接口的支持。
知道了怎样访问接口,我们还要知道怎样实现接口,要实现C#的接口,请看下一节-实现接口
前面我们已经说过,接口定义不包括方法的实现部分。接口可以通过类或结构来实现。我们主要讲述通过类来实现接口。用类来实现接口时,接口的名称必须包含在类定义中的基类列表中。
下面的例子给出了由类来实现接口的例子。其中ISequence 为一个队列接口,提供了向队列尾部添加对象的成员方法Add( ),IRing 为一个循环表接口,提供了向环中插入对象的方法Insert(object obj),方法返回插入的位置。类RingSquence 实现了接口ISequence 和接口IRing。
using System ; interface ISequence { object Add( ) ; } interface ISequence { object Add( ) ; } interface IRing { int Insert(object obj) ; } class RingSequence: ISequence, IRing { public object Add( ) {…} public int Insert(object obj) {…} } |
如果类实现了某个接口,类也隐式地继承了该接口的所有父接口,不管这些父接口有没有在类定义的基类表中列出。看下面的例子:
using System ; interface IControl { void Paint( ); } interface ITextBox: IControl { void SetText(string text); } interface IListBox: IControl { void SetItems(string[] items); } interface IComboBox: ITextBox, IListBox { } |
这里, 接口IcomboBox继承了ItextBox和IlistBox。类TextBox不仅实现了接口ITextBox,还实现了接口ITextBox 的父接口IControl。
前面我们已经看到,一个类可以实现多个接口。再看下面的例子:
interface IDataBound { void Bind(Binder b); } public class EditBox: Control, IControl, IDataBound { public void Paint( ); public void Bind(Binder b) {...} } |
类EditBox从类Control中派生并且实现了Icontrol和IdataBound。在前面的例子中接口Icontrol中的Paint方法和IdataBound接口中的Bind方法都用类EditBox中的公共成员实现。C#提供一种实现这些方法的可选择的途径,这样可以使执行这些的类避免把这些成员设定为公共的。接口成员可以用有效的名称来实现。例如,类EditBox可以改作方法Icontrol.Paint和IdataBound.Bind来来实现。
public class EditBox: IControl, IDataBound { void IControl.Paint( ) {...} void IDataBound.Bind(Binder b) {...} } |
因为通过外部指派接口成员实现了每个成员,所以用这种方法实现的成员称为外部接口成员。外部接口成员可以只是通过接口来调用。例如,Paint方法中EditBox的实现可以只是通过创建Icontrol接口来调用。
class Test { static void Main( ) { EditBox editbox = new EditBox( ); editbox.Paint( ); //错误: EditBox 没有Paint 事件 IControl control = editbox; control.Paint( ); // 调用 EditBox的Paint事件 } } |
上例中,类EditBox 从Control 类继承并同时实现了IControl and IDataBound 接口。EditBox 中的Paint 方法来自IControl 接口,Bind 方法来自IDataBound 接口,二者在EditBox 类中都作为公有成员实现。当然,在C# 中我们也可以选择不作为公有成员实现接口。
如果每个成员都明显地指出了被实现的接口,通过这种途径被实现的接口我们称之为显式接口成员(explicit interface member)。 用这种方式我们改写上面的例子:
public class EditBox: IControl, IDataBound { void IControl.Paint( ) {…} void IDataBound.Bind(Binder b) {…} } |
显式接口成员只能通过接口调用。例如:
class CTest { static void Main( ) { EditBox editbox = new EditBox( ) ; editbox.Paint( ) ; //错误:不同的方法 IControl control = editbox; control.Paint( ) ; //调用 EditBox的Paint方法 } } |
上述代码中对editbox.Paint( )的调用是错误的,因为editbox 本身并没有提供这一方法。control.Paint( )是正确的调用方式。
注释:接口本身不提供所定义的成员的实现,它仅仅说明这些成员,这些成员必须依靠实现接口的类或其它接口的支持。
知道了怎样访问接口,我们还要知道怎样实现接口,要实现C#的接口,请看下一节-实现接口