zoukankan      html  css  js  c++  java
  • C#进阶之路——10.C# 接口

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

    基础:

    接口 Interface

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

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

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

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

    1. using System;
    2. public interface ILogger
    3. {
    4. void Log(string Info);
    5. }
    6. public class TextLogger : ILogger
    7. {
    8.  public void Log(string Info)=> Console.Write("In base Logger");
    9. }

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

    进阶:

     

    接口

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

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

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

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

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

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

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

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

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

     

    C#接口中的默认方法

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

    1. public interface ILogger
    2. {
    3. void Log(string info);
    4. void Log(string typeofInformation,string info)

    }

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

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

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

    1. class Program
    2.     {
    3.         static void Main(string[] args)
    4.         {
    5.            ILogger _logger = new TextLogger();//将类对象作为接口进行实现。
    6.            _logger.LogInfo("Test","test"); // It will call the Default method of the interface
    7.         } 
    8.       }}

    注意:要访问默认接口方法,必须将其转型成接口。只有将类作为接口进行上下文处理时,接口默认方法才有效。否则如下图,类创建对象时,默认方法无法使用。

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

     

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

     

    接口语法要素

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

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

    private、protected、internal、public、virtual、abstract、override、sealed、static、extern\t

    静态字段

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

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

    Override修饰符

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

     

    示例

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

    1. Interface First
    2. {
    3.     void WritetoConsole() => Console.Write("In First");
    4. }
    5.  
    6. interface Second:First{
    7.  void First.WritetoConsole()=>Console.Write("In Second");
    8. }
    9.  

    interface Third:First{

      void First.WritetoConsole()=>Console.Write("In Third");

    }

     

    class FinalClass : Second,Third

    {

    }

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

     “Second.First.WritetoConsole()”和“ Third.First.WritetoConsole()”都不是具体的。

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

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

    1. using System;
    2. interface First
    3. {
    4.     void WritetoConsole() => Console.Write("In First");
    5. }
    6.  
    7. interface Second:First{
    8.  void First.WritetoConsole()=>Console.Write("In Second");
    9. }

     

    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的,则必须在具体类中实现。

    1. using System;
    2. interface IInterfaceModifiers
    3. {
    4.   //By Default default method is private
    5.   virtual void DefaultMethod()=>Console.WriteLine("Default method");
    6.   //Private Default Method
    7.   private void privatedefaultmethod()=>Console.WriteLine(" private Default method");
    8.   //Protected Default Method
    9.   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();

            }

       }

    }

     

    //控制台输出:

    1. Abstract virtual method
    2. Default method
    3. public Default method
    4. Virtual Default method

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

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

     来源:

    https://blog.csdn.net/mzl87/article/details/94626205

    https://blog.csdn.net/weixin_33755557/article/details/89129382

    https://www.cnblogs.com/LagoOrLY/p/10318214.html

    转载引用请注明出处。 文章作者:PaulTsao 文章来源:http://www.cnblogs.com/PaulTsao/ 作者信息:www.linkedin.com/apollocaoy
  • 相关阅读:
    Elasticsearch 分词
    Elasticsearch:文档乐观锁控制 if_seq_no与if_primary_term
    调用javaAPI访问hive
    sqoop笔记
    hive学习
    添加用户到sudo组
    HTTP协议用的TCP但是只建立单向连接
    Hadoop基本操作
    Hadoop原理介绍
    sed用法
  • 原文地址:https://www.cnblogs.com/PaulTsao/p/11486140.html
Copyright © 2011-2022 走看看