Jag*_*ddy 9 c# java default-interface-member
我听说在Java 8中可以灵活地在接口中使用函数定义.我认为我们可以在实现此类接口的所有类中具有此功能的默认状态.
那么,我的问题是我们今天在C#中有这样的功能吗?微软是否有这方面的计划?
默认接口方法是C#8的计划功能。
C#没有此功能,但是扩展方法解决了与Java中引入的默认方法相同的问题。
为了将类似LINQ的功能方法引入Java 8的通用集合中,语言设计人员希望有一种方法可以向诸如这样的接口添加方法Iterable<>
。毕竟,.filter(a -> ...).map(a -> ...)
语法比起来容易阅读得多map(filter(a ->...), a2 -> ...)
,这是他们仅添加实用程序方法所要做的事情。但是,仅在接口上添加方法签名将是一项重大突破,因为曾经实现该接口的任何人都会突然拥有无法在Java 8中构建的代码,除非他们实现了新方法。因此,他们开发了默认的实现方法,以便在现有接口上放置新方法不会破坏现有代码。
几年前,C#通过引入扩展方法解决了相同的问题。扩展方法不必真正更改接口本身,而只是使在实用程序类中定义的方法(如.Where()
和.Select()
上的方法IEnumerable<>
)更容易使用,就好像它实际上在目标对象上一样。
扩展方法和默认实现上的约束使它们在范围上非常相似。每种方法都有其优点和缺点,在这里我不再赘述,但从本质上讲,它们只是解决同一问题的两种不同方法。
与您的特定问题有关:扩展方法的缺点之一是(静态的)它们破坏了一些面向对象代码的最佳实践:它们之间可能存在命名冲突,并且您不能覆盖例如,它们可靠。因此,通常最好避免使用它们,除非您遇到无法通过其他任何方式轻松解决的问题。如果您只是希望提供方法的默认实现,通常最好改用基类,并期望人们扩展您的基类。
我想您会发现大多数Java专家都会对Java的默认实现持相同的看法。他们不是之前的Java 8中引入的,因为当时的看法是,接口都没有定义什么样的事情是能够做到的事情,而类是有定义如何这些事情完成。当然,您总能找到一些聪明的人,他们认为没有充分的理由首先拥有接口。但是,如果您使用的是接口,可能是因为您看到了定义合同而不提供实现细节的价值。引入了默认实现以解决一个非常具体的向后兼容性问题,如果您首先可以避免该问题,那么我看不出有任何真正好的理由使用它们。
扩展方法同时更危险,功能更强大,因此在向后兼容问题之外还有一些很好的用法,但是它们应该仍然谨慎使用,并且仅当其他面向对象的方法不起作用时才可以使用。
我同意迄今为止评论中的陈述 - C# 不支持这一点。据我所知,C# 没有计划支持这一点,也不应该支持。我也不同意 Java 8 包含此功能;我认为它混淆了接口和抽象基类。正如@AntP 在评论中所说,接口应该是契约(而不是指定行为)。
这里有两种可能的设计可以完成同样的事情(对仓促绘制的 UML 表示抱歉):
基本上,要点是您可以创建一个为所有子类添加默认实现的抽象基类,或者您可以为某些实现接口的子类创建一个基类(如果您想要这样做)。
显然其他设计也是可能的,该图主要用于说明目的。