介绍
去年9月,Microsoft使用C#8.0发布了许多新功能。 他们引入的主要功能之一是默认接口方法。 在这篇文章中,我们将解释它们是什么,展示一些示例,并提供避免常见陷阱的指南。
什么是C#8.0中的默认接口方法
C#中的接口曾经是定义或协定,没有任何行为。 这个假设不再成立。 现在,使用默认接口方法,您可以为任何接口方法定义默认主体。 这样做时,它们的行为就像抽象类中的虚拟方法。
为什么默认接口方法很重要
如果它们的行为像抽象类上的虚拟方法,为什么不简单地使用抽象类呢? 有一个很大的区别可以证明它们的存在:
在C#中,您只能从一个基类继承,但是可以实现所需的任意多个接口。
当涉及到代码重用时,也就是不要重复使用自己的(DRY)原则 ,这一微妙之处就变得至关重要 。 这项新功能将支持许多以前难以实现或无法实现的方案。
例如
- 通过在实现中添加方法来安全地扩展接口
- 创建参数化的实现以提供更大的灵活性
- 使实施者能够以覆盖的形式提供更具体的实施
默认接口方法的真实示例
没有默认接口方法
internal interface ILogger
{
void WriteCore ( LogLevel level, string message ) ;
void WriteInformation ( string message ) ;
void WriteWarning ( string message ) ;
void WriteError ( string message ) ;
}
internal class ConsoleLogger : ILogger
{
public void WriteCore ( LogLevel level, string message )
{
Console.WriteLine( $" {level} : {message} " );
}
public void WriteInformation ( string message )
{
this .WriteCore(LogLevel.Information, message);
}
public void WriteWarning ( string message )
{
this .WriteCore(LogLevel.Warning, message);
}
public void WriteError ( string message )
{
this .WriteCore(LogLevel.Error, message);
}
}
internal class TraceLogger : ILogger
{
public void WriteCore ( LogLevel level, string message )
{
switch (level)
{
case LogLevel.Information:
Trace.TraceInformation(message);
break ;
case LogLevel.Warning:
Trace.TraceWarning(message);
break ;
case LogLevel.Error:
Trace.TraceError(message);
break ;
}
}
public void WriteInformation ( string message )
{
this .WriteCore(LogLevel.Information, message);
}
public void WriteWarning ( string message )
{
this .WriteCore(LogLevel.Warning, message);
}
public void WriteError ( string message )
{
this .WriteCore(LogLevel.Error, message);
}
}
对于“ ILogger”的每个实现,我们都必须重复相同的代码块:
public void WriteInformation ( string message )
{
this .WriteCore(LogLevel.Information, message);
}
public void WriteWarning ( string message )
{
this .WriteCore(LogLevel.Warning, message);
}
public void WriteError ( string message )
{
this .WriteCore(LogLevel.Error, message);
}
使用默认接口方法
internal interface ILogger
{
void WriteCore ( LogLevel level, string message ) ;
void WriteInformation ( string message )
{
this .WriteCore(LogLevel.Information, message);
}
void WriteWarning ( string message )
{
this .WriteCore(LogLevel.Warning, message);
}
void WriteError ( string message )
{
this .WriteCore(LogLevel.Error, message);
}
}
internal class ConsoleLogger : ILogger
{
public void WriteCore ( LogLevel level, string message )
{
Console.WriteLine( $" {level} : {message} " );
}
}
internal class TraceLogger : ILogger
{
public void WriteCore ( LogLevel level, string message )
{
switch (level)
{
case LogLevel.Information:
Trace.TraceInformation(message);
break ;
case LogLevel.Warning:
Trace.TraceWarning(message);
break ;
case LogLevel.Error:
Trace.TraceError(message);
break ;
}
}
}
哈哈...这好多了。 现在,实现仅包含相关代码。
避免陷阱
尽管多重继承非常出色,但是您还需要非常注意可怕的钻石问题 。
当两个类B和C从A继承而类D从B和C继承时,就会产生歧义。如果A中有一个方法B和C都覆盖了它,而D没有覆盖它,那么哪个版本的D继承的方法:B的方法还是C的方法?
闭幕
在那里,您还有另一个很棒的工具可放入工具箱中,以保持代码的清洁和可维护。 这种方法也是非侵入性的,不会与现有代码冲突,这意味着很容易慢慢采用它。 如果您想了解更多有关此主题的信息,请在评论中告诉我。
参考文献
所有代码示例都可以在github上找到
From: https://hackernoon.com/what-are-default-interface-methods-in-c-80-9y4y3yol