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

posted @ 2019-09-08 14:40  PaulTsao  阅读(437)  评论(0编辑  收藏  举报