全面剖析C#接口编程之实现接口 (1)

C#开发——接口Interface C#开发接口Interface 阅读详情

 

 
发布时间:2003.03.13 09:40     来源:赛迪网    作者:黎宇

接口(interface)用来定义一种程序的协定。实现接口的类或者结构要与接口的定义严格一致。在前面的文章中,我们已经对C#接口的概念,如何定义接口以及如何对接口进行访问等问题进行了详细的讨论。在这些知识的基础上,本文我们将来了解实现接口的方法。

 

显式实现接口成员

为了实现接口,类可以定义显式接口成员执行体(Explicit interface member

implementations)。显式接口成员执行体可以是一个方法、一个属性、一个事件或者是一个索引指示器的定义,定义与该成员对应的全权名应保持一致。

using System ;
interface ICloneable {
    object Clone( ) ;
}
interface IComparable {
    int CompareTo(object other) ;
}
class ListEntry: ICloneable, IComparable {
    object ICloneable.Clone( ) {…}
    int IComparable.CompareTo(object other) {…}
}

上面的代码中ICloneable.Clone 和IComparable.CompareTo 就是显式接口成员执行体。

说明:

· 不能在方法调用、属性访问以及索引指示器访问中通过全权名访问显式接口成员执行体。事实上,显式接口成员执行体只能通过接口的实例,仅仅引用接口的成员名称来访问。

· 显式接口成员执行体不能使用任何访问限制符,也不能加上abstract, virtual, override或static 修饰符。

· 显式接口成员执行体和其他成员有着不同的访问方式。因为不能在方法调用、属性访问以及索引指示器访问中通过全权名访问,显式接口成员执行体在某种意义上是私有的。但它们又可以通过接口的实例访问,也具有一定的公有性质。

· 只有类在定义时,把接口名写在了基类列表中,而且类中定义的全权名、类型和返回类型都与显式接口成员执行体完全一致时,显式接口成员执行体才是有效的,例如:

class Shape: ICloneable {
    object ICloneable.Clone( ) {…}
    int IComparable.CompareTo(object other) {…}
}

使用显式接口成员执行体通常有两个目的:

· 因为显式接口成员执行体不能通过类的实例进行访问,这就可以从公有接口中把接口的实现部分单独分离开。如果一个类只在内部使用该接口,而类的使用者不会直接使用到该接口,这种显式接口成员执行体就可以起到作用。

· 显式接口成员执行体避免了接口成员之间因为同名而发生混淆。如果一个类希望对名称和返回类型相同的接口成员采用不同的实现方式,这就必须要使用到显式接口成员执行体。如果没有显式接口成员执行体,那么对于名称和返回类型不同的接口成员,类也无法进行实现。

下面的定义是无效的,因为Shape 定义时基类列表中没有出现接口IComparable。

class Shape: ICloneable
{
    object ICloneable.Clone( ) {…}
}
class Ellipse: Shape
{
    object ICloneable.Clone( ) {…}
}

在Ellipse中定义ICloneable.Clone是错误的,因为Ellipse即使隐式地实现了接口ICloneable,ICloneable仍然没有显式地出现在Ellipse定义的基类列表中。

接口成员的全权名必须对应在接口中定义的成员。如下面的例子中,Paint的显式接口成员执行体必须写成IControl.Paint。

using System ;
interface IControl
{
    void Paint( ) ;
}
interface ITextBox: IControl
{
    void SetText(string text) ;
}
class TextBox: ITextBox
{
    void IControl.Paint( ) {…}
    void ITextBox.SetText(string text) {…}
}

实现接口的类可以显式实现该接口的成员。当显式实现某成员时,不能通过类实例访问该成员,而只能通过该接口的实例访问该成员。显式接口实现还允许程序员继承共享相同成员名的两个接口,并为每个接口成员提供一个单独的实现。

下面例子中同时以公制单位和英制单位显示框的尺寸。Box类继承IEnglishDimensions和IMetricDimensions两个接口,它们表示不同的度量衡系统。两个接口有相同的成员名 Length 和 Width。

程序清单1  DemonInterface.cs
interface IEnglishDimensions  {
   float Length ( ) ;
   float Width ( ) ;
}
interface IMetricDimensions {
   float Length ( ) ;
   float Width ( ) ;
}
class Box : IEnglishDimensions, IMetricDimensions {
   float lengthInches ;
   float widthInches ;
   public Box(float length, float width) {
      lengthInches = length ;
      widthInches = width ;
   }
   float IEnglishDimensions.Length( ) {
      return lengthInches ;
   }
   float IEnglishDimensions.Width( ) {
      return widthInches ;      
   }
   float IMetricDimensions.Length( ) {
      return lengthInches * 2.54f ;
   }
   float IMetricDimensions.Width( ) {
      return widthInches * 2.54f ;
   }
   public static void Main( ) {
      //定义一个实类对象 "myBox"::
      Box myBox = new Box(30.0f, 20.0f);
      // 定义一个接口" eDimensions"::
      IEnglishDimensions eDimensions = (IEnglishDimensions) myBox;
      IMetricDimensions mDimensions = (IMetricDimensions) myBox;
      // 输出:
      System.Console.WriteLine(" Length(in): {0}", eDimensions.Length( ));
      System.Console.WriteLine(" Width (in): {0}", eDimensions.Width( ));
      System.Console.WriteLine(" Length(cm): {0}", mDimensions.Length( ));
      System.Console.WriteLine(" Width (cm): {0}", mDimensions.Width( ));
   }
}

输出:Length(in): 30,Width (in): 20,Length(cm): 76.2,Width (cm): 50.8

代码讨论:如果希望默认度量采用英制单位,请正常实现 Length 和 Width 这两个方法,并从 IMetricDimensions 接口显式实现 Length 和 Width 方法:

public float Length( ) {
   return lengthInches ;
}
public float Width( ){
   return widthInches;
}
float IMetricDimensions.Length( ) {
   return lengthInches * 2.54f ;
}
float IMetricDimensions.Width( ) {
   return widthInches * 2.54f ;
}

这种情况下,可以从类实例访问英制单位,而从接口实例访问公制单位:

System.Console.WriteLine("Length(in): {0}", myBox.Length( )) ;
System.Console.WriteLine("Width (in): {0}", myBox.Width( )) ;    
System.Console.WriteLine("Length(cm): {0}", mDimensions.Length( )) ;
System.Console.WriteLine("Width (cm): {0}", mDimensions.Width( )) ;

 

继承接口实现

接口具有不变性,但这并不意味着接口不再发展。类似于类的继承性,接口也可以继承和发展。

注意:接口继承和类继承不同,首先,类继承不仅是说明继承,而且也是实现继承;而接口继承只是说明继承。也就是说,派生类可以继承基类的方法实现,而派生的接口只继承了父接口的成员方法说明,而没有继承父接口的实现,其次,C#中类继承只允许单继承,但是接口继承允许多继承,一个子接口可以有多个父接口。

接口可以从零或多个接口中继承。从多个接口中继承时,用":"后跟被继承的接口名字,多个接口名之间用","分割。被继承的接口应该是可以访问得到的,比如从private类型或internal类型的接口中继承就是不允许的。接口不允许直接或间接地从自身继承。和类的继承相似,接口的继承也形成接口之间的层次结构。

请看下面的例子:

using System ;
interface IControl {
    void Paint( ) ;
}
interface ITextBox: IControl {
    void SetText(string text) ;
}
interface IListBox: IControl {
    void SetItems(string[] items) ;
}
interface IComboBox: ITextBox, IListBox { }

对一个接口的继承也就继承了接口的所有成员,上面的例子中接口ITextBox和IListBox都从接口IControl中继承,也就继承了接口IControl的Paint方法。接口IComboBox从接口ITextBox和IListBox中继承,因此它应该继承了接口ITextBox的SetText方法和IListBox的SetItems方法,还有IControl的Paint方法。

一个类继承了所有被它的基本类提供的接口实现程序。

不通过显式的实现一个接口,一个派生类不能用任何方法改变它从它的基本类继承的接口映射。例如,在声明中:

interface IControl {
	void Paint( );
}
class Control: IControl {
	public void Paint( ) {...}
}
class TextBox: Control {
	new public void Paint( ) {...}
}

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( ) ;			// 影响Control.Paint( ) ;
t.Paint( ) ;			// 影响TextBox.Paint( ) ;
ic.Paint( ) ;			// 影响Control.Paint( ) ;
it.Paint( ) ;			// 影响Control.Paint( ) ;

但是,当一个接口方法被映射到一个类中的虚拟方法,派生类就不可能覆盖这个虚拟方法并且改变接口的实现函数。例如,把上面的声明重新写为:

interface IControl {
	void Paint( ) ;
}
class Control: IControl {
	public virtual void Paint( ) {...}
}
class TextBox: Control {
	public override void Paint( ) {...}
}

就会看到下面的结果:

Control c = new Control( ) ;
TextBox t = new TextBox( ) ;
IControl ic = c ;
IControl it = t ;
c.Paint( ) ;			// 影响Control.Paint( );
t.Paint( ) ;			// 影响TextBox.Paint( );
ic.Paint( ) ;			// 影响Control.Paint( );
it.Paint( ) ;			// 影响TextBox.Paint( );

由于显式接口成员实现程序不能被声明为虚拟的,就不可能覆盖一个显式接口成员实现程序。一个显式接口成员实现程序调用另外一个方法是有效的,而另外的那个方法可以被声明为虚拟的以便让派生类可以覆盖它。例如:

interface IControl {
	void Paint( ) ;
}
class Control: IControl {
	void IControl.Paint( ) { PaintControl( ); }
	protected virtual void PaintControl( ) {...}
}
class TextBox: Control {
	protected override void PaintControl( ) {...}
}

这里,从Control继承的类可以通过覆盖方法PaintControl来对IControl.Paint的实现程序进行特殊化。

 

 

C#编程项目CPAS1核心概念教程 本文还有配套的精品资源,点击获取 简介:CPAS1是可能与C#编程密切相关的项目或软件。C#是一种面向对象的编程语言,广泛用于Windows桌面、游戏、Web和移动应用开发。本文将介绍C#的核心概念,包括基础语法、类与对象、命名空间、异常处理、LINQ、异步编程、泛型、事件和委托、接口、.NET框架、***以及C#新版本特性。理解这些关键点对于掌握C#编程至关重要。 ... 阅读详情

相关推荐

C#接口编程实战:Interface类库源码与程序演示

在C#语言体系中,接口不仅是实现多态性的核心机制之一,更是构建可扩展、高内聚、低耦合软件架构的重要基石。与类不同,接口不提供具体实现,而是作为一种契约存在——它规定了实现类必须具备的行为特征。这种“只声明、不实现”的特性使得接口成为抽象层次更高的设计工具。深入理解接口的定义方式及其成员规范,是掌握现代C#编程的关键一步。本章将从interface关键字的本质语义出发,系统剖析其语法结构与典型使用场景,并进一步探讨接口命名约定和设计原则。

weixin_32747681的博客 974

C#中的接口

简单介绍了C#中的接口,包括了类对接口的实现,接口之间的继承等。

weixin_66598341的博客 5788

【STM32】基于STM32F103C8T6实现步进电机精准调速控制

本文详细介绍了如何使用STM32F103C8T6微控制器实现步进电机的精准调速控制。通过利用其内置定时器生成PWM脉冲,替代低效的延时方法,并结合TB6600驱动器进行硬件连接,可实现平滑、高效的电机速度控制。文章提供了基于HAL库的代码实战,包括速度与方向设置函数,并探讨了加减速规划等高级应用,帮助开发者彻底掌握步进电机驱动技术。

weixin_29169899的博客 485

C#面向接口编程

C#面向接口编程

qq_38567182的博客 1800

Qi标准下的充电协议及其记忆技巧

记忆无线充电协议中的。

m0_73991989的博客 1319

避坑指南:用Adams做滚珠丝杠仿真时90%人会遇到的3个建模错误

本文针对使用Adams进行滚珠丝杠动力学仿真时常见的三大建模错误,提供了详细的避坑指南。重点解析了如何避免因直接导入CAD几何体导致的性能与精度问题,科学设置接触参数以提升计算效率与结果平滑度,以及通过规范的命名与组织管理模型,确保仿真过程高效可靠。

gin88的博客 573

自学笔记C#

如果你不想使用线程来解决语音播报时间过长导致 WinForm UI 假死的问题,你可以考虑使用异步操作来执行语音播报。使用异步操作可以避免在 UI 线程上执行长时间的操作,从而保持 UI 界面的响应。你可以使用 C# 的异步关键字async和await来简化异步编程。i在上面的示例代码中,事件处理程序使用async关键字修饰,表示这是一个异步方法。在方法内部,我们使用await操作符来等待SpeechTask方法的完成。在SpeechTask方法中,我们使用Task.Delay。

weixin_45182597的博客 342

如何从RHEL 8升级到RHEL 9

Red Hat 于 2022 年 5 月 17 日宣布全面推出 RHEL 9。这是 RHEL(Red Hat Enterprise Linux)的最新版本,它具有许多功能和增强功能。

u012748257的博客 1019

C#学习教程07——接口

C#学习教程,适合新手小白,附带学习源码。

Kint的博客 2142

学Simulink——基于Simulink的Buck-Boost变换器双闭环PI+抗饱和设计建模示例

本文详细介绍了基于Simulink的非反相Buck-Boost变换器双闭环控制设计方法。针对Buck-Boost变换器特有的右半平面零点(RHPZ)和控制挑战,提出了电压-电流双闭环PI控制架构,并集成抗积分饱和机制。通过Simulink建模,实现了主电路、电流内环PI、电压外环PI、PWM及占空比限幅等模块的搭建,验证了在输入电压跌落(20V→10V)和负载突变(2A→4A)等场景下的稳定性能。仿真结果表明,输出电压波动小于0.35V,恢复时间快于1ms,电感电流有效限幅。文章还讨论了工程实践要点和扩展方

xiaoheshang_123的博客 318

从 OPEN CURSOR 到 SELECT INTO TABLE:把 ABAP 数据读取的底层机制与性能差异讲透

ABAP数据库访问性能优化关键点 摘要:ABAP程序性能的核心在于数据读取方式的选择。本文分析了三种常见数据库访问方式的技术原理:显式游标(CURSOR)、SELECT-ENDSELECT循环和SELECT INTO TABLE。重点揭示了数据从数据库到应用服务器的传输机制,包括OPEN/REOPEN与FETCH操作、Array Fetch批量传输原理以及SAP游标缓存机制。通过VBAK表的性能测试数据对比,证明了不同场景下最优访问方式的选择依据:大数据量时显式游标性能优势明显,而SELECT INTO T

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 172

全面剖析C#接口编程之实现接口

function StorePage(){d=document;t=d.selection?(d.selection.type!=None?d.selection.createRange().text:):(d.getSelection?d.getSelection():);void(keyit=window.open(http://www.365key.com/storeit.

363

Sigrity System SI SerialLink模式进行Pcie3协议仿真分析操作指导-pcie3_client_single_pre

Sigrity System SI SerialLink模式提供了10个协议合规性检查工具模板,用户可以将根据实际应用替换模板中的SPICE文件,然后进行协议仿真分析,同时软件还提供了目标结果的模板MASK以及该协议需要检查的项目,通过协议分析视为满足设计要求,下面介绍pcie3_client_single_pre仿真分析,具体操作如下。Random(Rj):随机抖动,该抖动用高斯概率分布来描述,通常是由热噪声和其它随机噪声引起的,默认为1.24%UI RMS(平均值),即和标准值的偏差为1.24%UI。

weixin_54787054的博客 598

全面剖析C#接口编程之定义接口

从技术上讲,接口是一组包含了函数型方法的数据结构。通过这组数据结构,客户代码可以调用组件对象的功能。 定义接口的一般形式为: [attributes] [modifiers] interface identifier [:base-list] {interface-bod

旅途 2136

SAP 系统间信任关系配置全攻略:从 SM59 到 SMT1 的实践与风险控制

本文介绍了在SAP系统间配置信任关系的详细流程与最佳实践。文章以SAP Gateway与后端系统架构为场景,从SM59创建RFC目的地开始,到SMT1建立信任关系,再到授权对象S_RFCACL的配置,提供了完整的操作指南。重点包括:使用标准命名规范创建专用RFC连接、通过向导完成系统间信任登记、严格控制S_RFCACL授权范围等。文中还分享了真实项目案例、可复用的检查清单以及常见问题的排查思路,帮助用户实现稳定可靠的跨系统无密码调用,同时确保安全性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 323

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

全面剖析C#接口编程之实现接口 (2)

全面剖析C#接口编程之实现接口 (2)   重新实现接口我们已经介绍过,派生类可以对基类中已经定义的成员方法进行重载。类似的概念引入到类对接口 的实现中来,叫做接口的重实现(re-implementation)。继承了接口实现的类可以对接口进行重实现。这个接口要求是在类定义的基类

516

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

上一篇: asp.net設置報表和子報表
下一篇: 全面剖析C#接口编程之实现接口 (2)
jackeyabc
博客等级 码龄20年 71粉丝 297原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值