当前位置:首页 > C#教程 > C#高级

C#进阶之路——10.C# 接口

基础:

接口 interface

应用:接口是方法的抽象,如果不同的类有同样的方法,那么就应该考虑使用接口。

形式:名称始终冠以大写字母i

特点:接口不会出现方法体,没有修饰符,由实现类提供方法体并为其分配一些修饰符,如果类没有实现该方法会编译错误。

 

接口示例:定义ilogger接口实现文本日志输出

  • using system;
  • public interface ilogger
  • {
  • void log(string info);
  • }
  • public class textlogger : ilogger
  • {
  •  public void log(string info)=> console.write("in base logger");
  • }
  •  

    在此定义了一个拥有一个log()方法的ilogger接口。并有一个叫做实现接口ilogger的textlogger类,输出一个文本日志。

     

    进阶:

     

    接口

    1、一个接口就相当于一个抽象类,在接口中不能实现任何方法,属性或者索引器。

    2、不能包含任何具体实现方法,接口中的方法不能重写,只能实现,接口的每种方法都必须在派生类中实现。

    3、接口有时候可以看成是类的模具,它指明一个类该提供哪些内容。

    4、接口主体只限于方法、索引器、属性的声明,不能包含字段、构造函数和常量等,指定方法只需给出返回类型、名称和参数列表,然后以分号结束。

    6、接口成员是隐式公开的,如果对其显式指定访问级别,就会出现编译器错误。

    7、实现接口的语法与实现继承一样,都用冒号“:”

    c#中多重接口的实现,弥补了c#只能单一继承,不能多重继承的缺点。

    如果两个接口中有完全相同的签名,可以用“接口名.方法名”的方式显式实现接口。

    一个类要实现一个接口,必须为基接口和派生接口的所有成员编写实现代码。

     

    c#接口中的默认方法

    接口示例:扩展ilogger接口并在其中添加更多信息

     

  • public interface ilogger
  • {
  • void log(string info);
  • void log(string typeofinformation,string info)
  • }

    当接口被多个类使用,根据使用此接口的位置在实现中进行这些更改代价很大。实现这个方法就需要使用c#8接口中的默认方法。

    在c#中,类不允许多重继承,接口也只在有限的范围内进行多重继承,而且不包含状态。

    此时为了在应用程序中使用此接口,需要改变main方法,要访问默认接口方法,必须将其转型成接口。

  • class program
  •     {
  •         static void main(string[] args)
  •         {
  •            ilogger _logger = new textlogger();//将类对象作为接口进行实现。
  •            _logger.loginfo("test","test"); // it will call the default method of the interface
  •         } 
  •       }}
  • 注意:要访问默认接口方法,必须将其转型成接口。只有将类作为接口进行上下文处理时,接口默认方法才有效。否则如下图,类创建对象时,默认方法无法使用。

    注意:c# 默认接口会产生多重继承问题,即钻石问题。

     

     

    即在main中没有将类作为接口进行处理,则找不到对应接口方法。

     

     

    接口语法要素

    接口语法已经经过扩展,可接受下面列出的新关键字。例如,你可以在接口中编写一个私有方法,代码仍然可以通过编译并正常工作。

    方法体或索引器、属性、事件访问器

    private、protected、internal、public、virtual、abstract、override、sealed、static、externt

    静态字段

    静态方法、属性、索引器和事件

    具有默认访问权限的显式访问修饰符是public的

    override修饰符

    不允许出现:实例状态、实例字段、实例自动属性

     

     

    示例

    c#接口默认方法中钻石问题的解决

  • interface first
  • {
  •     void writetoconsole() => console.write("in first");
  • }
  •  
  • interface second:first{
  •  void first.writetoconsole()=>console.write("in second");
  • }
  •  
  • interface third:first{

      void first.writetoconsole()=>console.write("in third");

    }

     

    class finalclass : second,third

    {

    }

    编译出现错误:接口成员' first.writetoconsole()'没有最具体的实现。

     “second.first.writetoconsole()”和“ third.first.writetoconsole()”都不是具体的。

    为了解决错误本身所描述的这个问题,我们需要在执行时提供最具体的覆盖。

    dotnet设计团队通过在运行时调用最具体的覆盖方法来解决钻石问题:“接口成员的类实现应该总是胜过接口中的默认实现,即使它是从基类继承的。只有当类没有提供具体的实现时,才考虑使用默认实现”。

  • using system;
  • interface first
  • {
  •     void writetoconsole() => console.write("in first");
  • }
  •  
  • interface second:first{
  •  void first.writetoconsole()=>console.write("in second");
  • }
  •  

    interface third:first{

      void first.writetoconsole()=>console.write("in third");

    }

     

    class finalclass : second,third

    {

      void first.writetoconsole(){

      console.write("from final class");

    }

    }

    注意:在覆盖的方法中不允许出现访问修饰符。这里关键字virtual和abstract可以没有,不过有对编译后的代码也没有任何影响。

    c#8.0之后可以在接口中使用修饰符private,protected,internal,public和virtual。

    所有默认接口的方法都是virtual,可以自主设置为private或sealed。

    没有正文的所有成员在默认情况下都被视为抽象,则必须在具体类中实现。

    接口语法现在可以接受以下关键字:protected、internal、public和virtual。c#8.0之后可以在接口中使用修饰符private。

    默认情况下,接口方法是virtual的,除非使用了sealed或private修饰符。

    类似的,没有方法体的接口成员默认是abstract的,则必须在具体类中实现。

  • using system;
  • interface iinterfacemodifiers
  • {
  •   //by default default method is private
  •   virtual void defaultmethod()=>console.writeline("default method");
  •   //private default method
  •   private void privatedefaultmethod()=>console.writeline(" private default method");
  •   //protected default method
  •   protected void protecteddefaultmethod()=>console.writeline(" protected default method");
  •   // public default method

      public void publicdefaultmethod()=>console.writeline(" public default method");

      virtual void virtualdefaultmethod()=>console.writeline("virtual default method");

      abstract void abstractdefaultmethod();

    }

    class interfacemodifierdemo : iinterfacemodifiers

      public void abstractdefaultmethod() => console.writeline("abstract virtual method");

    }

     

    //main方法中

    namespace deaultinterfacedemo

    {

        class program

        {

            static void main(string[] args)

            {

                iinterfacemodifiers i= new interfacemodifierdemo();

                i.abstractdefaultmethod();

                i.defaultmethod();

                i.publicdefaultmethod();

                i.virtualdefaultmethod();

            }

       }

    }

     

    //控制台输出:

  • abstract virtual method
  • default method
  • public default method
  • virtual default method
  • //当我们创建一个protected方法时,它在继承接口中可用,而不是实现类。

    //默认情况下,接口的成员是abstract,这使得实现类必须正确实现它们。

     


    【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!