说明(2017-7-17 21:57:26):

原文:http://www.cnblogs.com/jiajiayuan/archive/2011/09/16/2178462.html

本文意在巩固基础知识,并不是对其进行深入剖析,还望理解。
本文为原创文,难免会有一些小得瑕疵,敬请谅解。
所有示例均是博主测试过的,如有转载请标明出处,谢谢。
在编程中,我们经常会用到接口,那什么是接口呢?
接口描述的是可属于任何类或结构的一组相关功能,所以实现接口的类或结构必须实现接口定义中指定的接口成员。
接口使用interface 关键字进行定义,可由方法、属性、事件、索引器或这四种成员类型的任意组合构成。
接口的特性:
1.接口类似于抽象基类,不能直接实例化接口;接口中的方法都是抽象方法,实现接口的任何非抽象类型都必须实现接口的所有成员:
显式实现该接口的成员时,实现的成员不能通过类实例访问,只能通过接口实例访问。
隐式实现该接口的成员时,实现的成员可以通过类实例访问,也可以通过接口实例访问,但是实现的成员必须是公有的
2.接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型、不能包含静态成员。
3.接口成员是自动公开的,且不能包含任何访问修饰符。
4.接口自身可从多个接口继承,类和结构可继承多个接口,但接口不能继承类。
为什么不能指定接口中方法的修饰符? 
接口中的方法用来定义对象之间通信的契约,指定接口中的方法为私有或保护没有意义。它们默认为公有方法。

interface IProgram
{
void Fun();
}
class Program:IProgram
{
//显式实现接口成员
void IProgram.Fun()
{
Console.WriteLine("I am Fun.");
}
staticvoid Main(string[] args)
{
IProgram p =new Program(); //声明一个接口实例,但不是对接口进行实例化
p.Fun();
Console.Read();
}
}

上面提到,实现接口可以显式实现和隐式实现,那么这两种实现到底有什么优缺点呢?
一般情况,当类或者结构要实现的是单个接口,可以使用隐式实现。
如果类或者结构继承了多个接口且接口中具有相同名称成员时,就要用到显式实现,当显式实现方式存在时,隐式实现方式就失效了。

interface IProgram
{
void Fun();
}
interface IAProgram
{
void Fun();
}
class Program : IProgram, IAProgram
{
void IProgram.Fun() //显式实现接口IProgram
{
Console.WriteLine("I am IProgram Fun.");
}
void IAProgram.Fun() //显式实现接口IAProgram
{
Console.WriteLine("I am IAProgram Fun.");
}
//public void Fun() //隐式实现接口
//{
// Console.WriteLine("I am Program Fun.");
//}
staticvoid Main(string[] args)
{
//IProgram p = new Program();
//p.Fun();
//IAProgram ap = new Program();
//ap.Fun();
Program pro =new Program();
((IProgram)pro).Fun();
((IAProgram)pro).Fun();
Console.Read();
}
}

结果为:I am IProgram Fun.
           I am IAProgram Fun.
接口的继承:
接口继承和类继承不同:首先,类继承不仅是说明继承,而且也是实现继承;而接口继承只是说明继承。
也就是说,派生类可以继承基类的方法实现,而派生的接口只继承了父接口的成员方法说明,而没有继承父接口的实现,
其次,C#中类继承只允许单继承,但是接口继承允许多继承,一个子接口可以有多个父接口。
接口可以从零或多个接口中继承。从多个接口中继承时,用":"后跟被继承的接口名字,多个接口名之间用","分割。
被继承的接口应该是可以访问得到的,比如从private 类型或internal 类型的接口中继承就是不允许的。
接口不允许直接或间接地从自身继承。和类的继承相似,接口的继承也形成接口之间的层次结构。

    interface IProgram
{
void Fun();
}
interface IAProgram:IProgram
{ }
class Program : IAProgram
{
void IProgram.Fun()
{
Console.WriteLine("I am IProgram Fun.");
}
staticvoid Main(string[] args)
{
Program pro =new Program();
((IAProgram)pro).Fun();
Console.Read();
}
}

接口的覆盖:
由于接口的实现没有方法体,抽象方法也没有方法体,那么当我们在接口的实现方法里调用抽象方法时,会如何执行呢?

    interface IProgram
{
void Fun();
}
abstractclass AProgram : IProgram
{
publicabstractvoid AFun();
void IProgram.Fun()
{
AFun();
}
}
class Program:AProgram
{
publicoverridevoid AFun()
{
Console.WriteLine("I am AProgram.");
}
staticvoid Main(string[] args)
{
IProgram pro =new Program();
pro.Fun();
Console.Read();
}
}
//结果:I am Aprogram.

通过断点,可以看到,当执行pro.Fun();时,首先会跳到接口的实现方法里,然后去调用抽象函数的实现方法,当抽象函数的方法实现后,再回到接口的实现方法,直到执行完成。
当我们在实现接口的方法里调用虚函数呢?

    interface IProgram
{
void Fun();
}
class AProgram : IProgram
{
publicvirtualvoid AFun() //注意这里是虚函数
{
Console.WriteLine("I am virtual AFun.");
}
void IProgram.Fun()
{
AFun();
}
}
class Program:AProgram
{
publicoverridevoid AFun() //这里是Override重写
{
Console.WriteLine("I am override AFun.");
}
staticvoid Main(string[] args)
{
IProgram pro =new Program();
pro.Fun();
Console.Read();
}
}

这时,我们发现,执行的顺序和上一个例子是相同的。所以结果为:I am override AFun.
由此,我们可以继续联想,当我们把override关键字,换成new呢?是不是也是同样的结果,还是和我们以前讲的例子一样,是隐藏呢?
我们把上面的例子进行改进:

interface IProgram
{
void Fun();
}
class AProgram : IProgram
{
publicvirtualvoid AFun()
{
Console.WriteLine("I am virtual AFun.");
}
void IProgram.Fun()
{
AFun();
}
}
class Program:AProgram
{
publicnewvoid AFun()
{
Console.WriteLine("I am new AFun.");
}
staticvoid Main(string[] args)
{
Program pro =new Program();
((IProgram)pro).Fun();
pro.AFun();
Console.Read();
}
}

结果为:I am virtual AFun.
           I am new AFun.
由于前面已经讲过了,这里不在对此进行分析,由此我们可知使用New关键字是对其进行隐藏,当对接口实现的方法里调用的是虚方法时,和类的执行过程是一样的。
接口和抽象类的区别。

接口用于规范,抽象类用于共性。
接口中只能声明方法,属性,事件,索引器。而抽象类中可以有方法的实现,也可以定义非静态的类变量。
抽象类是类,所以只能被单继承,但是接口却可以一次实现多个。
抽象类可以提供某些方法的部分实现,接口不可以。
抽象类的实例是它的子类给出的。接口的实例是实现接口的类给出的。 
在抽象类中加入一个方法,那么它的子类就同时有了这个方法。而在接口中加入新的方法,那么实现它的类就要重新编写(这就是为什么说接口是一个类的规范了)。
接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。
此外接口不能包含字段、构造函数、析构函数、静态成员或常量。 
C#中的接口和类有什么异同。 
异: 
不能直接实例化接口。 
接口不包含方法的实现。 
接口可以实现多继承,而类只能是单继承。 
类定义可在不同的源文件之间进行拆分。 
同: 
接口、类和结构可从多个接口继承。 
接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。 
接口可以包含事件、索引器、方法和属性。 
一个类可以实现多个接口。

C#学习笔记(15)——c#接口的更多相关文章

  1. 并发编程学习笔记(15)----Executor框架的使用

    Executor执行已提交的 Runnable 任务的对象.此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节.调度等)分离开来的方法.通常使用 Executor 而不是显式地创建 ...

  2. Ext.Net学习笔记15:Ext.Net GridPanel 汇总(Summary)用法

    Ext.Net学习笔记15:Ext.Net GridPanel 汇总(Summary)用法 Summary的用法和Group一样简单,分为两步: 启用Summary功能 在Feature标签内,添加如 ...

  3. SQL反模式学习笔记15 分组

    目标:查询得到每组的max(或者min等其他聚合函数)值,并且得到这个行的其他字段 反模式:引用非分组列 单值规则:跟在Select之后的选择列表中的每一列,对于每个分组来说都必须返回且仅返回一直值. ...

  4. Typescript 学习笔记六:接口

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  5. Java学习笔记之---比较接口与抽象类

    Java学习笔记之---比较接口与抽象类 抽象类是描述事物的本质,接口是描述事物的功能 接口与抽象类的异同 1.一个类只能继承一个父类,但是可以有多个接口 2.抽象类中的抽象方法没有方法体,但是可以有 ...

  6. Linux内核学习笔记之seq_file接口创建可读写proc文件

    转自:http://blog.csdn.net/mumufan05/article/details/45803219 学习笔记与个人理解,如有错误,欢迎指正. 温馨提示:建议跟着注释中的编号顺序阅读代 ...

  7. [原创]java WEB学习笔记15:域对象的属性操作(pageContext,request,session,application) 及 请求的重定向和转发

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  8. Adaptive AUTOSAR 学习笔记 15 - 持久化 Persistency

    本系列学习笔记基于 AUTOSAR Adaptive Platform 官方文档 R20-11 版本 AUTOSAR_EXP_PlatformDesign.pdf.作者:Zijian/TENG 原文地 ...

  9. Beego 学习笔记15:布局页面

    页面布局 1>     一个html页面由:head部分,body部分,内部css,内部js,外联css,外联的js这几部分组成.因此,一个布局文件也就需要针对这些进行拆分. 2>     ...

  10. 【设计模式】学习笔记15:代理模式(Proxy Pattern)

    本文出自   http://blog.csdn.net/shuangde800 本笔记内容: 1. JAVA远程代理调用(RMI) 2. 代理模式 走进代理模式 在上一篇的状态模式中,我们实现了一个糖 ...

随机推荐

  1. 构建高性能web之路------mysql读写分离实战(转)

    一个完整的mysql读写分离环境包括以下几个部分: 应用程序client database proxy database集群 在本次实战中,应用程序client基于c3p0连接后端的database ...

  2. 模拟器集成3DTouch-b

    本文主要讲解3DTouch各种场景下的集成,开发主屏幕应用icon上的快捷选项标签(Home Screen Quick Actions),静态设置 UIApplicationShortcutItem ...

  3. C语言下的错误处理的问题

    下面是三种C语言的错误处理,你喜欢哪一种?还是都不喜欢? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /* 问题: 不充分,而且很容易出错,前 ...

  4. POJ 1129 Channel Allocation(DFS)

    Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13173   Accepted: 67 ...

  5. 常用的代码之一:用StopWatch计算代码运行花费的时间。

    先引用Diagnostics using System.Diagnostics; 然后: Stopwatch stopWatch = new Stopwatch(); stopWatch.Start( ...

  6. SNF微信公众号客户端演示-微信开发客户端能干什么

    关注测试微信号: 关注后菜单页面如下: 一.扫描二维码进行订单查询演示 1.点击菜单“软件产品”->选择“扫描查询” 2.扫描如下二维码进行订单查询演示. 3.扫描结果如下: 二.微信“输入订单 ...

  7. 发布Asp.net core到nginx 使用nginx代理

    In this guide, we will cover setting up a production-ready ASP.NET environment on an Ubuntu 16.04 Se ...

  8. struts2:JSON在struts中的应用(JSP页面中将对象转换为JSON字符串提交、JSP页面中获取后台Response返回的JSON对象)

    JSON主要创建如下两种数据对象: 由JSON格式字符串创建,转换成JavaScript的Object对象: 由JSON格式字符串创建,转换成JavaScript的List或数组链表对象. 更多关于J ...

  9. Android应用的基本原理

    原文:http://android.eoe.cn/topic/android_sdk 应用基础-Application Fundamentals Android应用程序以java作为开发语言.用And ...

  10. [CTCI] 最长合成字符串

    最长合成字符串 题目描述 有一组单词,请编写一个程序,在数组中找出由数组中字符串组成的最长的串A,即A是由其它单词组成的(可重复)最长的单词. 给定一个string数组str,同时给定数组的大小n.请 ...