当前位置: 首页 > 编程日记 > 正文

Visual C#访问接口

对接口成员的访问

对接口方法的调用和采用索引指示器访问的规则与类中的情况也是相同的。如果底层成员的命名与继承而来的高层成员一致,那么底层成员将覆盖同名的高层成员。但由于接口支持多继承,在多继承中,如果两个父接口含有同名的成员,这就产生了二义性(这也正是C#中取消了类的多继承机制的原因之一),这时需要进行显式的定义:

using System ;

interface ISequence {

int Count { get; set; }

}

interface IRing {

void Count(int i) ;

}

interface IRingSequence: ISequence, IRing { }

class CTest {

void Test(IRingSequence rs) {

//rs.Count(1) ; 错误, Count 有二义性

//rs.Count = 1; 错误, Count 有二义性

((ISequence)rs).Count = 1; // 正确

((IRing)rs).Count(1) ; // 正确调用IRing.Count

}

}

上面的例子中,前两条语句rs .Count(1)和rs .Count = 1会产生二义性,从而导致编译时错误,因此必须显式地给rs 指派父接口类型,这种指派在运行时不会带来额外的开销。

再看下面的例子:

using System ;

interface IInteger {

void Add(int i) ;

}

interface IDouble {

void Add(double d) ;

}

interface INumber: IInteger, IDouble {}

class CMyTest {

void Test(INumber Num) {

// Num.Add(1) ; 错误

Num.Add(1.0) ; // 正确

((IInteger)n).Add(1) ; // 正确

((IDouble)n).Add(1) ; // 正确

}

}

调用Num.Add(1) 会导致二义性,因为候选的重载方法的参数类型均适用。但是,调用Num.Add(1.0) 是允许的,因为1.0 是浮点数参数类型与方法IInteger.Add()的参数类型不一致,这时只有IDouble.Add 才是适用的。不过只要加入了显式的指派,就决不会产生二义性。

接口的多重继承的问题也会带来成员访问上的问题。例如:

interface IBase {

void FWay(int i) ;

}

interface ILeft: IBase {

new void FWay (int i) ;

}

interface IRight: IBase

{ void G( ) ; }

interface IDerived: ILeft, IRight { }

class CTest {

void Test(IDerived d) {

d. FWay (1) ; // 调用ILeft. FWay

((IBase)d). FWay (1) ; // 调用IBase. FWay

((ILeft)d). FWay (1) ; // 调用ILeft. FWay

((IRight)d). FWay (1) ; // 调用IBase. FWay

}

}

上例中,方法IBase.FWay在派生的接口ILeft中被Ileft的成员方法FWay覆盖了。所以对d. FWay (1)的调用实际上调用了。虽然从IBase-> IRight-> IDerived这条继承路径上来看,ILeft.FWay方法是没有被覆盖的。我们只要记住这一点:一旦成员被覆盖以后,所有对其的访问都被覆盖以后的成员"拦截"了。

类对接口的实现

前面我们已经说过,接口定义不包括方法的实现部分。接口可以通过类或结构来实现。我们主要讲述通过类来实现接口。用类来实现接口时,接口的名称必须包含在类定义中的基类列表中。

下面的例子给出了由类来实现接口的例子。其中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#的接口,请看下一节-实现接口

类对接口的实现

前面我们已经说过,接口定义不包括方法的实现部分。接口可以通过类或结构来实现。我们主要讲述通过类来实现接口。用类来实现接口时,接口的名称必须包含在类定义中的基类列表中。

下面的例子给出了由类来实现接口的例子。其中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( )是正确的调用方式。

注释:接口本身不提供所定义的成员的实现,它仅仅说明这些成员,这些成员必须依靠实现接口的类或其它接口的支持。

转载于:https://www.cnblogs.com/lovenets/articles/422099.html

相关文章:

powerdesigner类图在子类中显示从父类继承来的方法

首先确保画了子类和父类之间的继承线 然后在子类的选项卡中点击

[UML]UML系列——用例图中的各种关系(include、extend)

[UML]UML系列——用例图中的各种关系(include、extend) 原文:[UML]UML系列——用例图中的各种关系(include、extend)用例图中的各种关系 一、参与者与用例间的关联关系 参与者与用例之间的通信,也成为关联或通信关系。…

熬夜写了一个小游戏,向SpaceX聊表敬意

2019独角兽企业重金招聘Python工程师标准>>> 这是我长久放在桌面上的一张图片。 这张照片的名字叫做 Pale Blue Dot(暗淡蓝点),是旅行者1号在距地球64亿公里回望太阳系时所拍下的。照片右侧中部有一个隐约可见的小蓝点&#xff0c…

【转】Linux Oracle服务启动停止脚本与开机自启动

在CentOS 6.3下安装完Oracle 10g R2,重开机之后,你会发现Oracle没有自行启动,这是正常的,因为在Linux下安装Oracle的确不会自行启动,必须要自行设置相关参数,首先先介绍一般而言如何启动oracle。 一、在Lin…

ASP.Net中MD5加密-16位32位

publicstringmd5(stringstr,intcode){if(code16) //16位MD5加密(取32位加密的9~25字符){return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str,"MD5").ToLower().Substring(8,16) ;} else//32位加密{retur…

PL/SQL编程:将两个数进行交换的存储过程

创建过程exchangeTwo 调用过程enchangeTwo

WCF之多个终结点

1.服务端配置如下&#xff08;一个Service节点下可有多个endpoint,&#xff09;&#xff1a; 1 1<system.serviceModel>2 2 <services>3 3 <service name"Microsoft.ServiceModel.Samples.CalculatorService" behaviorConfiguration"returnFaul…

YAML 语言入门教程

2019独角兽企业重金招聘Python工程师标准>>> YAML简介 另一种标记语言&#xff08;Yet Another Markup Language&#xff09; YAML&#xff08;英语发音&#xff1a;/ˈjməl/&#xff0c;尾音类似camel骆驼&#xff09;是一个可读性高&#xff0c;用来表达资料序列…

我翻译的一篇文章,OO设计中对象的创建和使用

OO设计中对象的创建和使用 转载于:https://www.cnblogs.com/lishu1980/archive/2006/06/22/432526.html

SQL Server Profiler工具

SQL Server Profiler工具 原文:SQL Server Profiler工具一、SQL Profiler工具简介 SQL Profiler是一个图形界面和一组系统存储过程&#xff0c;其作用如下&#xff1a; 图形化监视SQL Server查询&#xff1b;在后台收集查询信息&#xff1b;分析性能&#xff1b;诊断像死锁之类…

Nginx—核心配置location匹配规则说明

2019独角兽企业重金招聘Python工程师标准>>> location介绍 location指令是Nginx中最核心的一项配置&#xff0c;根据预先定义的URL匹配规则来接收用户发送的请求&#xff0c;根据匹配结果&#xff0c;将请求转发到后台服务器、非法的请求直接拒绝并返回403&#xff…

Windows Live Messenger  正式版已经发布

Windows Live Messenger 正式版已经发布!这是新一代的 Messenger。它拥有全新的名字&#xff0c;可以免费下载。并且除了延续使用原 Messenger 的全部功能外&#xff0c;它还提供了几种出色的全新交流方式&#xff0c;实现与朋友的即时共享和交流。转载于:https://www.cnblogs.…

关闭ubuntu启动时System Program Problem Detected提示

修改vi /etc/default/apport 将其值设置1-->0转载于:https://www.cnblogs.com/snail-micheal/p/3607969.html

C++开源跨平台类库集

在如下的库支持下&#xff0c;开发的系统可以很方便移植到当前大部分平台上运行而无需改动&#xff0c;只需在对应的平台下 用你喜欢的编译器 重新编译即可 经典的C库 STLport-------SGI STL库的跨平台可移植版本&#xff0c;在以前有些编译器离符合 标准比较远的情况…

僵尸进程和孤儿进程

一 . 僵尸进程: 子进程退出&#xff0c;父进程没有回收子进程资源&#xff08;PCB&#xff09;&#xff0c;则子进程变成僵尸进程 处理僵尸进程的方法&#xff1a;wait 和 waitpid 调用wait和waitpid不仅可以获得子进程的终止信息&#xff0c;还可以使父进程阻塞等待子进程终止…

Castle ActiveRecord(一)概述

一、ActiveRecord与Castle ActiveRecordActiveRecord是《Patterns of Enterprise Application Architecture》中描述的著名模式。基本上&#xff0c;当实例每一行的时候&#xff0c;所有的静态方法会作用于全部纪录。 Castle ActiveRecord 是ActiveRecord 模式的一个实现&am…

一步步学习SPD2010--第十一章节--处理母版页(8)--从母版页创建网页

一步步学习SPD2010--第十一章节--处理母版页&#xff08;8&#xff09;--从母版页创建网页 在SPD中&#xff0c;你可以使用许多不同的方法创建ASP.NET页面。然而&#xff0c;因为页面将是SP网站的一部分&#xff0c;你很可能想像其他页面一样&#xff0c;保持相同的导航元素和外…

Confluence 6 查看空间活动

空间活动信息是默认禁用&#xff08;disabled by default&#xff09;的。活动&#xff08;Activity&#xff09;的标没有显示&#xff0c;如果你的 Confluence Usage Stats 插件没有启用的。请查看下面的说明&#xff1a; 如果启用的话&#xff0c;空间活动界面显示了每一个空…

flash模拟EEROM

FLASH中&#xff1a;0x08000000--0x08000000SIZE保存的是用户代码 Rule&#xff1a; 16位为传输单位 读数据&#xff1a; u16 STMFLASH_ReadHalfWord(u32 faddr) 可以在通用地址空间直接寻址&#xff1a;data*(vu16*)ADDR;[ADDR为32位数据&#xff0c;指向的数据为uv16型]写数据…

OSChina 周六乱弹 —— 就少个接吻的女友了

2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单&#xff08;2018&#xff09;请戳&#xff08;这里&#xff09; 【今日歌曲】 andonny &#xff1a;分享Mamas & The Papas的单曲《California Dreaming》 《California Dreaming》- Mamas & The …

存儲過程解密SQL

存儲過程解密SQLif exists (select * from dbo.sysobjects where id object_id(N[dbo].[sp_decrypt]) and OBJECTPROPERTY(id, NIsProcedure) 1)drop procedure [dbo].[sp_decrypt]GO /*--破解函數,視圖,程儲過程,触發器,限于SQLSERVER2000 --作者:J9988--*//*--使用示例 --解…

软件缺陷生命周期图示及当中涉及到的缺陷的状态

缺陷状态&#xff1a; 激活/打开 已修正 已关闭/非激活 重新打开(对应图示验证通过否N) 推迟(对应图示的延期) 保留(对应图示无法解决) 不能重现 需要更多信息

Adding a QR Code Reader in Flex on Android

<?xml version"1.0" encoding"utf-8"?> <s:View xmlns:fx"http://ns.adobe.com/mxml/2009" xmlns:mx"library://ns.adobe.com/flex/mx"xmlns:s"library://ns.adobe.com/flex/spark" title"HomeView"&g…

41-高级路由:BGP AS长度:接收一切、最大AS长度、不比较AS长度

一、实验拓扑&#xff1a;二、实验要求&#xff1a;1、R4配置同上个实验&#xff1b;2、R3配置接收的路由包含最大AS长度为4&#xff1b;3、R3配置隐藏命令&#xff0c;不比较AS长度&#xff1b;4、R5配置不管收到的路由有没有包含本地AS都收入&#xff08;之前R4已经配置了4.4…

利用动态加载模板,配合ajax实现无刷新操作

关键字&#xff1a;DataGrid 动态模板 Ajax我们使用ajax实现无刷新界面时&#xff0c;对于DataGrid&#xff0c;Repeater等列表还是比较麻烦的&#xff0c;经过我的尝试&#xff0c;找出一种比较合理的方法&#xff0c;可以免除对html的加工处理&#xff0c;随时获取到数据列表…