深入理解C#之接口

目录
  • C#之接口
    • 接口的特性:
    • 接口的继承:
    • 接口的覆盖:
    • 接口和抽象类的区别。
    • C#中的接口和类有什么异同。
  • 总结

C#之接口

在编程中,我们经常会用到接口,那什么是接口呢?

接口描述的是可属于任何类或结构的一组相关功能,所以实现接口的类或结构必须实现接口定义中指定的接口成员。

接口使用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#中的接口和类有什么异同。

异:

  • 不能直接实例化接口。
  • 接口不包含方法的实现。
  • 接口可以实现多继承,而类只能是单继承。
  • 类定义可在不同的源文件之间进行拆分。

同:

  • 接口、类和结构可从多个接口继承。
  • 接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
  • 接口可以包含事件、索引器、方法和属性。
  • 一个类可以实现多个接口。

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,并在文章页面明显位置以超链接形式注明出处,否则保留追究法律责任的权利。

总结

本篇文章就到这里了,希望能给你带来帮助,也希望你能够多多关注我们的更多内容!

(0)

相关推荐

  • C#中接口(Interface)的深入详解

    定义 在 C# 语言中,类之间的继承关系仅支持单重继承,而接口是为了实现多重继承关系设计的.一个类能同时实现多个接口,还能在实现接口的同时再继承其他类,并且接口之间也可以继承.无论是表示类之间的继承还是类实现接口.接口之间的继承,都使用":"来表示. 接口定义了属性.方法和事件,这些都是接口的成员.接口只包含了成员的声明.成员的定义是派生类的责任.接口提供了派生类应遵循的标准结构.接口定义了语法合同 "是什么" 部分,派生类定义了语法合同 "怎么做&quo

  • c#如何实现接口事件

    接口可以声明事件. 下面的示例演示如何在类中实现接口事件. 这些规则基本上都与实现任何接口方法或属性时的相同. 在类中实现接口事件 在类中声明事件,然后在相应区域中调用它. namespace ImplementInterfaceEvents { public interface IDrawingObject { event EventHandler ShapeChanged; } public class MyEventArgs : EventArgs { // class members }

  • c#发送请求访问外部接口的实例

    我就废话不多说了,大家还是直接看代码吧~ string url = "https://cloud.soei.com.cn/smsapi/sms/verifycode"; HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(url); //表头参数 string token = "9c0025b4aae442bda5498971ec1ab219"; httpClient.

  • C#调用Python的URL接口的示例

    VS2013的简单WInForm控件,通过WebRequest,WebResponse来访问,接收: private void btn_interface_Click(object sender, EventArgs e) { string url = "http://127.0.0.1:5000"; WebRequest wRequest = WebRequest.Create(url); wRequest.Method = "GET"; wRequest.Con

  • 在C# 8中如何使用默认接口方法详解

    前言 C# 8 中新增了一个非常有趣的特性,叫做 默认接口方法 (又称虚拟扩展方法),这篇文章将会讨论 C# 8 中的默认接口方法以及如何使用. 在 C# 8 之前,接口不能包含方法定义,只能在接口中定义方法签名,还有一个就是接口的成员默认是 public 和 abstract , 在 C# 8 之前,接口不能包含字段,也不能包含private, protected, 或者 internal 的方法成员.如果你在接口中引入了一个新成员,默认情况下你必须更新实现该接口的所有子类. 在 C# 8 中

  • 深入理解Android之接口回调机制

    刚开始学对于这个机制理解不够深刻,现在重新整理下思路.开发中,接口回调是我们经常用到的. 接口回调的意思即,注册之后并不立马执行,而在某个时机触发执行. 首先解决啥是回调: 举个例子:某天,我打电话向你请教问题,当然是个难题,你一时想不出解决方法,我又不能拿着电话在那里傻等,于是我们约定:等你想出办法后打手机通知我,这样,我就挂掉电话办其它事情去了.过了XX分钟,我的手机响了,你兴高采烈的说问题已经搞定,应该如此这般处理. C不会自己调用b,C提供b的目的就是让S来调用它,而且C不得不提供.S并

  • 深入理解Java的接口与抽象类

    对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的时候会以为它们可以随意互换使用,但是实际则不然.今天我们就一起来学习一下Java中的接口和抽象类.下面是本文的目录大纲: 一.抽象类 二.接口 三.抽象类和接口的区别 一.抽象类 在了解抽象类之前,先来了解一下抽象方法.抽象方法是一种特殊的方法:它只有声明,而没有具体的实现.抽象方法的声明格式为: abstract void fu

  • 深入理解C#之接口

    目录 C#之接口 接口的特性: 接口的继承: 接口的覆盖: 接口和抽象类的区别. C#中的接口和类有什么异同. 总结 C#之接口 在编程中,我们经常会用到接口,那什么是接口呢? 接口描述的是可属于任何类或结构的一组相关功能,所以实现接口的类或结构必须实现接口定义中指定的接口成员. 接口使用interface 关键字进行定义,可由方法.属性.事件.索引器或这四种成员类型的任意组合构成. 接口的特性: 1.接口类似于抽象基类,不能直接实例化接口:接口中的方法都是抽象方法,实现接口的任何非抽象类型都必

  • 深入理解Java class文件格式_动力节点Java学院整理

    Class文件在Java体系结构中的位置和作用 对于理解JVM和深入理解Java语言, 学习并了解class文件的格式都是必须要掌握的功课. 原因很简单, JVM不会理解我们写的Java源文件, 我们必须把Java源文件编译成class文件, 才能被JVM识别, 对于JVM而言, class文件相当于一个接口, 理解了这个接口, 能帮助我们更好的理解JVM的行为:另一方面, class文件以另一种方式重新描述了我们在源文件中要表达的意思, 理解class文件如何重新描述我们编写的源文件, 对于深

  • C++ COM编程之接口背后的虚函数表

    前言 学习C++的人,肯定都知道多态机制:多态就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.对于多态机制是如何实现的,你有没有想过呢?而COM中的接口就将这一机制运用到了极致,所以,不知道多态机制的人,是永运无法明白COM的.所以,在总结COM时,是非常有必要专门总结一下C++的多态机制是如何实现的. 多态 什么是多态?上面也说了,多态就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.现在通过代码,让大家切身的体会一下多态: 复制代

  • 浅谈Java 8 新增函数式接口到底是什么

    从 Java 8 开始便出现了函数式接口(Functional Interface,以下简称FI) 定义为: 如果一个接口只有唯一的一个抽象接口,则称之为函数式接口.为了保证接口符合 FI ,通常会在接口类上添加 @FunctionalInterface 注解.理解了函数式接口可以为 Java 函数式编程打下基础,最终可通过运用函数式编程极大地提高编程效率. 函数式接口 (Functional Interface) 就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口. 函数式接口可以对

  • Java语法之 Java 的多态、抽象类和接口

    目录 一.多态 1. 向上转型 2. 动态绑定 3. 方法重写 4. 向下转型 5. 关键字 super 6. 在构造方法中调用重写方法(坑) 7. 理解多态 8. 小结 二.抽象类 1. 概念 2. 注意事项 3. 抽象类的意义 3. 抽象类的作用 三.接口 1. 语法规则 2. 实现多个接口 3. 接口的继承 4. Comparable 接口 4. Comparator 接口 5. Cloneable 接口和深拷贝 上一篇文章:Java 基础语法之解析 Java 的包和继承 今天这章主要介绍

  • JavaSE的三大接口:Comparator,Comparable和Cloneable详解

    进阶JavaSE-三大接口:Comparator.Comparable和Cloneable. Comparable和Comparator这两个接口很相似,都是用于比较大小的接口.在我们写一些数据结构的算法题时,用的比较多,具体是怎么用的,我们接着往下看. Comparator接口: public interface Comparator<T> { public int compare(T o1, T o2); //比较方法 } Comparable接口: public interface Co

  • 详解Java 中的函数式接口

    目录 @FunctionalInterface注解 最简单的函数式接口 基础数据类型的函数表达式 二元输入参数的函数 Two-Arity Function Specializations Suppliers 供给型接口 & Consumers 消费型接口 Predicates 断言型接口 Operators 总结 @FunctionalInterface注解 如果你想自己定义个新的函数式接口,强烈建议你加上*@FunctionalInterface* 注解.可以更好地揭示我们定义这个接口的意思,

  • Flutter 语法进阶抽象类和接口本质区别详解

    目录 1. 接口存在的意义? 2. 继承 VS 实现 3. Dart 中接口与实现的特殊性 4.Dart 中抽象类作为接口的小细节 1. 接口存在的意义? 在 Dart 中 接口 定义并没有对应的关键字.可能有些人觉得 Dart 中弱化了 接口 的概念,其实不然.我们一般对接口的理解是:接口是更高级别的抽象,接口中的方法都是 抽象方法 ,没有方法体.通过接口的定义,我们可以通过定义接口来声明功能,通过实现接口来确保某类拥有这些功能. 不过你有没有仔细想过,为什么接口会存在,引入接口的概念是为了解

随机推荐