运维开发网
广告位招商联系QQ:123077622
 
广告位招商联系QQ:123077622

深入理解C#之接口

运维开发网 https://www.qedev.com 2021-07-09 11:28 出处:网络 作者: 佳园
目录C#之接口接口的特性:接口的继承:接口的覆盖:接口和抽象类的区别。C#中的接口和类有什么异同。总结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.");
            //}
           http://www.cppcns.com 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();
            }
        }
    AbcXmdAeId

    结果为:

    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 Ma编程客栈in(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();
    www.cppcns.com          www.cppcns.com  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#中的接口和类有什么异同。

    异:

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

    同:

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

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

    总结

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

    扫码领视频副本.gif

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消