C#进阶之路——10. C# 接口
基础:
接口 Interface |
接口是方法的抽象,如果不同的类有同样的方法,那么就应该考虑使用接口。 |
接口名称:始终冠以大写字母I |
接口不会出现方法体,没有修饰符,实现类提供方法体并为其分配一些修饰符,如果类没有实现该方法会编译错误。 |
接口示例:定义ILogger接口实现文本日志输出 |
|
在此定义了一个拥有一个Log()方法的ILogger接口。并有一个叫做实现接口ILogger的TextLogger类,输出一个文本日志。 |
进阶:
接口 |
1、一个接口就相当于一个抽象类,但是它不能包含任何实现方法。 2、接口的每种方法都必须在派生类中实现。 3、接口有时候可以看成是类的模具,它指明一个类该提供哪些内容。 4、接口主体只限于方法、索引器、属性的声明。 5、接口中不能包含字段、构造函数和常量等。 6、接口成员是隐式公开的,如果对其显式指定访问级别,就会出现编译器错误。 7、在接口中不能实现任何方法,属性或者索引器。 8、在指定方法时,只需给出返回类型、名称和参数列表,然后以分号结束。 9、实现接口的语法与实现继承一样,都用冒号“:” 10、接口中的方法不能重写,只能实现。 |
C#中多重接口的实现,弥补了C#只能单一继承,不能多重继承的缺点。 |
如果两个接口中有完全相同的签名,可以用“接口名.方法名”的方式显式实现接口。 |
一个类要实现一个接口,必须为基接口和派生接口的所有成员编写实现代码。 |
C#接口中的默认方法 |
接口示例:扩展ILogger接口并在其中添加更多信息 |
|
} |
当接口被多个类使用,根据使用此接口的位置在实现中进行这些更改代价很大。实现这个方法就需要使用C#8接口中的默认方法。 |
在C#中,类不允许多重继承,接口也只在有限的范围内进行多重继承,而且不包含状态。 |
此时为了在应用程序中使用此接口,需要改变main方法,要访问默认接口方法,必须将其转型成接口。 |
|
注意:要访问默认接口方法,必须将其转型成接口。只有将类作为接口进行上下文处理时,接口默认方法才有效。否则如下图,类创建对象时,默认方法无法使用。 |
注意:C# 默认接口会产生多重继承问题,即钻石问题。 |
|
即在main中没有将类作为接口进行处理,则找不到对应接口方法。
接口语法要素 |
接口语法已经经过扩展,可接受下面列出的新关键字。例如,你可以在接口中编写一个私有方法,代码仍然可以通过编译并正常工作。 |
方法体或索引器、属性、事件访问器 private、protected、internal、public、virtual、abstract、override、sealed、static、extern\\t 静态字段 静态方法、属性、索引器和事件 具有默认访问权限的显式访问修饰符是public的 Override修饰符 |
不允许出现:实例状态、实例字段、实例自动属性 |
示例 |
C#接口默认方法中钻石问题的解决 |
interface Third:First{ void First.WritetoConsole()=>Console.Write("In Third"); }
class FinalClass : Second,Third { } |
编译出现错误:接口成员‘ First.WritetoConsole()‘没有最具体的实现。 “Second.First.WritetoConsole()”和“ Third.First.WritetoConsole()”都不是具体的。 |
为了解决错误本身所描述的这个问题,我们需要在执行时提供最具体的覆盖。 Dotnet设计团队通过在运行时调用最具体的覆盖方法来解决钻石问题:“接口成员的类实现应该总是胜过接口中的默认实现,即使它是从基类继承的。只有当类没有提供具体的实现时,才考虑使用默认实现”。 |
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的,则必须在具体类中实现。 |
// 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(); } } }
|
//控制台输出:
|
//当我们创建一个protected方法时,它在继承接口中可用,而不是实现类。 //默认情况下,接口的成员是abstract,这使得实现类必须正确实现它们。 |
|
来源:
https://blog.csdn.net/mzl87/article/details/94626205
https://blog.csdn.net/weixin_33755557/article/details/89129382