简体   繁体   English

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

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

I heard that in Java 8 there is a flexibility of having function definitions in an Interface. 我听说在Java 8中可以灵活地在接口中使用函数定义。 I think we can have some default state with this feature in all the classes that are implementing such interface. 我认为我们可以在实现此类接口的所有类中具有此功能的默认状态。

So, my question is do we have any such feature in C# as of today? 那么,我的问题是我们今天在C#中有这样的功能吗? Are there any plans from Microsoft on this regard ? 微软是否有这方面的计划?

Update 更新

Default Interface Methods are a planned feature for C# 8 . 默认接口方法是C#8的计划功能

Original Answer 原始答案

C# doesn't have this exact feature, but Extension Methods solve the same problems that default methods were introduced to solve in Java. C#没有这个确切的功能,但是扩展方法解决了在Java中引入默认方法的相同问题。

In order to introduce LINQ-like functional methods to common collections in Java 8, the language designers wanted a way to add methods to interfaces like Iterable<> . 为了向Java 8中的公共集合引入类似LINQ的函数方法,语言设计者想要一种方法来向Iterable<>Iterable<>添加方法。 After all, the .filter(a -> ...).map(a -> ...) syntax is much easier to read than map(filter(a ->...), a2 -> ...) , which is what they'd have had to do if they just added utility methods. 毕竟, .filter(a -> ...).map(a -> ...)语法比map(filter(a ->...), a2 -> ...)更容易阅读map(filter(a ->...), a2 -> ...)如果他们只是添加了实用工具方法,那就是他们必须要做的事情。 However, just adding a method signature to an interface would have been a breaking change because anybody who ever implemented that interface would suddenly have code that doesn't build in Java 8 unless they implemented the new methods. 然而,仅仅向接口添加方法签名将是一个重大变化,因为任何实现该接口的人都会突然拥有不使用Java 8构建的代码,除非他们实现了新方法。 So they developed default implementation methods so that putting new methods on an existing interface wouldn't break existing code. 因此,他们开发了默认的实现方法,以便在现有接口上放置新方法不会破坏现有代码。

Years earlier, C# had solved the same problem by introducing Extension Methods. 几年前,C#通过引入扩展方法解决了同样的问题。 Rather than actually changing the interface itself, an Extension method just makes it easy to use a method (like .Where() and .Select() methods on an IEnumerable<> ) defined in a utility class, as if it were actually on the target object. 而不是实际更改接口本身,Extension方法只是使得在实用程序类中定义的方法(如IEnumerable<>上的.Where().Select()方法.Where()变得容易,就好像它实际上在目标对象。

The constraints put on Extension Methods and Default Implementations make them both very similar in scope. 扩展方法和默认实现的约束使它们在范围上非常相似。 There are some advantages and disadvantages to each, which I won't go into here, but in essence they are just two different approaches to solve the same problem. 每个都有一些优点和缺点,我不会在这里讨论,但实质上它们只是解决同一问题的两种不同方法。

As it relates to your specific question: one of the downsides of Extension methods is that (being static) they break some of the best-practices of object-oriented code: it's possible to have naming collisions between them, and you can't override them reliably, for example. 因为它与您的具体问题有关:扩展方法的一个缺点是(静态)它们破坏了面向对象代码的一些最佳实践:它们之间可能存在命名冲突,并且您无法覆盖例如,它们是可靠的。 So it's usually best to avoid them unless you have a problem that cannot easily be solved in any other way. 所以通常最好避免它们,除非你有一个不能以任何其他方式轻易解决的问题。 If you're just hoping to provide a default implementation of a method, you're typically better off using a base class instead, and expecting people to extend your base class. 如果您只是希望提供方法的默认实现,那么通常最好使用基类,并期望人们扩展您的基类。

I think you'd find that most Java experts would say the same thing about Default Implementations in Java. 我想你会发现大多数Java专家会对Java中的Default Implementations说同样的话。 They weren't introduced prior to Java 8 because the prevailing wisdom is that interfaces are there to define what a thing is capable of doing, whereas classes are there to define how those things are done. 他们不是之前的Java 8中引入的,因为当时的看法是,接口都没有定义什么事情能够做到的事情,而类是有定义这些事情是如何完成的。 Of course, you can always find a few smart people who think there's no good reason to have interfaces in the first place . 当然,你总能找到一些聪明的人,他们认为没有充分的理由首先拥有接口 But if you're using interfaces, it's presumably because you see value in defining a contract without providing implementation details. 但是,如果您正在使用接口,那么可能是因为您在定义合同时看到了价值而没有提供实现细节。 Default Implementations were introduced to solve a very specific backwards-compatibility problem, and if you can avoid that problem in the first place then there's not any really good reason I can see to use them. 引入了默认实现来解决一个非常具体的向后兼容性问题,如果你可以首先避免这个问题,那么我没有任何理由可以使用它们。

Extension methods are at the same time more dangerous and more powerful, so there are some good uses for them outside of the backwards-compatibility problem, but they should still be used sparingly and only when other more object-oriented approaches won't work. 扩展方法同时更危险,更强大,因此除了向后兼容性问题之外,它们还有一些很好的用途,但它们仍应谨慎使用,并且只有在其他更加面向对象的方法不起作用时才能使用。

The official language proposal for default interface implementations in C# is documented here: 这里记录了C#中默认接口实现的官方语言提议:

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

It is currently marked with status of "proposal". 它目前标有“提案”状态。

With that said, there are numerous use cases for it which are altogether very strong. 话虽如此,它有很多用例,它们非常强大。 At present, it seems very likely to be approved as indicated by Mass Torgerson and Dustin Campbell in the video below. 目前,看起来很有可能被Mass Torgerson和Dustin Campbell在下面的视频中表示批准。 If so, it is almost certainly in line to be released with C#8. 如果是这样的话,几乎可以肯定与C#8一起发布。

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

Around 53:00, the discussion begins and a demo is shown. 大约53:00,讨论开始并显示演示。

C# 8.0 will introduce the new feature of default interface implementations. C#8.0将介绍默认接口实现的新功能。 This is useful when new methods are added to keep compatibility with existing implementations of the interface. 添加新方法以保持与现有接口实现的兼容性时,这非常有用。 It could also provide simple default implementations like shown in the following example: 它还可以提供简单的默认实现,如以下示例所示:

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

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

New C# featues 新的C#特色

I agree with the statements made in the comments so far - C# doesn't support this. 我同意到目前为止评论中的陈述 - C#不支持这一点。 As far as I know there's no plan to support this in C#, nor should it be supported. 据我所知,没有计划在C#中支持这一点,也不应该支持它。 I disagree with Java 8 including this feature as well; 我不同意Java 8,包括这个功能; I think it conflates interfaces and abstract base classes. 我认为它混淆了接口和抽象基类。 As @AntP said in the comments, interfaces should be contracts (not to specify behavior). 正如@AntP在评论中所说,接口应该是契约(而不是指定行为)。

Here are two possible designs that accomplish the same thing (and sorry about the hastily-drawn UML): 以下是两种可能完成同样事情的设计(对于草率绘制的UML感到遗憾): 在此输入图像描述

Basically, point being you can either create an abstract base class that adds default implementations for all child classes, or you can have a base class for some of the child classes that implements the interfaces if that's what you're trying to do. 基本上,重点是你可以创建一个为所有子类添加默认实现的抽象基类,或者你可以为一些实现接口的子类创建一个基类,如果你正在尝试这样做的话。

Obviously other designs are possible, this diagram is mostly just for the purposes of illustration. 显然其他设计是可能的,该图主要仅用于说明目的。

C# does not supports this but I disagree with the comments which says interfaces should be contract not implementation. C#不支持这一点,但我不同意那些说接口应该是契约而不是实现的注释。 Because the default implementations are not for the sack of implementation it is for the sack of keeping clients free from implementing the newly updated interfaces and not let their old cold break if they do not use new methods introduced in new versions of the api they used before. 因为默认实现不适用于实现,所以如果他们不使用他们之前使用的新版本api中引入的新方法,那么就不会让客户端无法实现新更新的接口。

The default methods in java 8 implementation really helped solve real problems that arrived after updating api. java 8实现中的默认方法确实有助于解决更新api后到达的实际问题。

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

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