繁体   English   中英

C#相当于Java 8接口中的默认方法

[英]C# equivalent of Java 8 Default Methods in Interface

我听说在Java 8中可以灵活地在接口中使用函数定义。 我认为我们可以在实现此类接口的所有类中具有此功能的默认状态。

那么,我的问题是我们今天在C#中有这样的功能吗? 微软是否有这方面的计划?

更新

默认接口方法是C#8的计划功能

原始答案

C#没有这个确切的功能,但是扩展方法解决了在Java中引入默认方法的相同问题。

为了向Java 8中的公共集合引入类似LINQ的函数方法,语言设计者想要一种方法来向Iterable<>Iterable<>添加方法。 毕竟, .filter(a -> ...).map(a -> ...)语法比map(filter(a ->...), a2 -> ...)更容易阅读map(filter(a ->...), a2 -> ...)如果他们只是添加了实用工具方法,那就是他们必须要做的事情。 然而,仅仅向接口添加方法签名将是一个重大变化,因为任何实现该接口的人都会突然拥有不使用Java 8构建的代码,除非他们实现了新方法。 因此,他们开发了默认的实现方法,以便在现有接口上放置新方法不会破坏现有代码。

几年前,C#通过引入扩展方法解决了同样的问题。 而不是实际更改接口本身,Extension方法只是使得在实用程序类中定义的方法(如IEnumerable<>上的.Where().Select()方法.Where()变得容易,就好像它实际上在目标对象。

扩展方法和默认实现的约束使它们在范围上非常相似。 每个都有一些优点和缺点,我不会在这里讨论,但实质上它们只是解决同一问题的两种不同方法。

因为它与您的具体问题有关:扩展方法的一个缺点是(静态)它们破坏了面向对象代码的一些最佳实践:它们之间可能存在命名冲突,并且您无法覆盖例如,它们是可靠的。 所以通常最好避免它们,除非你有一个不能以任何其他方式轻易解决的问题。 如果您只是希望提供方法的默认实现,那么通常最好使用基类,并期望人们扩展您的基类。

我想你会发现大多数Java专家会对Java中的Default Implementations说同样的话。 他们不是之前的Java 8中引入的,因为当时的看法是,接口都没有定义什么事情能够做到的事情,而类是有定义这些事情是如何完成的。 当然,你总能找到一些聪明的人,他们认为没有充分的理由首先拥有接口 但是,如果您正在使用接口,那么可能是因为您在定义合同时看到了价值而没有提供实现细节。 引入了默认实现来解决一个非常具体的向后兼容性问题,如果你可以首先避免这个问题,那么我没有任何理由可以使用它们。

扩展方法同时更危险,更强大,因此除了向后兼容性问题之外,它们还有一些很好的用途,但它们仍应谨慎使用,并且只有在其他更加面向对象的方法不起作用时才能使用。

这里记录了C#中默认接口实现的官方语言提议:

https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md

它目前标有“提案”状态。

话虽如此,它有很多用例,它们非常强大。 目前,看起来很有可能被Mass Torgerson和Dustin Campbell在下面的视频中表示批准。 如果是这样的话,几乎可以肯定与C#8一起发布。

https://channel9.msdn.com/Events/Build/2017/B8104

大约53:00,讨论开始并显示演示。

C#8.0将介绍默认接口实现的新功能。 添加新方法以保持与现有接口实现的兼容性时,这非常有用。 它还可以提供简单的默认实现,如以下示例所示:

public interface ILogger  
{
    void Log(LogLevel level, string message);

    void Log(LogLevel level, string format, params object[] arguments)
    {
        Log(level, string.Format(format, arguments));
    }
}

新的C#特色

我同意到目前为止评论中的陈述 - C#不支持这一点。 据我所知,没有计划在C#中支持这一点,也不应该支持它。 我不同意Java 8,包括这个功能; 我认为它混淆了接口和抽象基类。 正如@AntP在评论中所说,接口应该是契约(而不是指定行为)。

以下是两种可能完成同样事情的设计(对于草率绘制的UML感到遗憾): 在此输入图像描述

基本上,重点是你可以创建一个为所有子类添加默认实现的抽象基类,或者你可以为一些实现接口的子类创建一个基类,如果你正在尝试这样做的话。

显然其他设计是可能的,该图主要仅用于说明目的。

C#不支持这一点,但我不同意那些说接口应该是契约而不是实现的注释。 因为默认实现不适用于实现,所以如果他们不使用他们之前使用的新版本api中引入的新方法,那么就不会让客户端无法实现新更新的接口。

java 8实现中的默认方法确实有助于解决更新api后到达的实际问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM