41

我正在寻找与 C# 扩展方法功能等效的 java。现在我一直在阅读 Java 8 的默认方法,但据我所知,我只能将这些添加到接口中......

...是否有任何语言功能可以让我为不实现接口的最终类​​编写扩展方法?(我宁愿不必包装它......)

4

4 回答 4

30

Java 没有扩展方法。默认方法不是扩展方法。让我们看看每个功能。

默认方法

Java 和 C# 都支持此功能

解决的问题:

  1. 许多对象可能实现相同的接口,并且它们都可能对方法使用相同的实现。基类可以解决这个问题,但前提是接口实现者还没有基类,因为 java 和 C# 都不支持多重继承。
  2. API 希望在不破坏 API 使用者的情况下向接口添加方法。添加具有默认实现的方法可以解决此问题。

Java 或 C# 的默认方法是向接口添加默认实现的功能。因此扩展接口的对象不必实现该方法,它们可以使用默认方法。

interface IA { default public int AddOne(int i) { return i + 1; } }

任何实现 IA 的对象都不必实现 AddOne,因为有一个默认方法可以使用。

public class MyClass implements IA { /* No AddOne implementation needed */ } 

C# 现在在 C# 8(或 .Net 5)中具有此功能

C#的扩展方法

解决的问题:

  1. 能够向密封类添加方法。
  2. 能够在不强制继承的情况下从第三方库向类添加方法。
  3. 能够在由于约定原因不允许模型类中的方法的环境中向模型类添加方法。
  4. IntelliSense 向您呈现这些方法的能力。

示例:字符串类型是 C# 中的密封类。您不能从字符串继承,因为它是密封的。但是您可以添加可以从字符串调用的方法。

var a = "mystring";
a.MyExtensionMethed()

Java 缺少这个特性,并且通过添加这个特性会得到很大的改进。

结论

Java 的默认方法和 C# 的扩展方法特性没有任何相似之处。它们完全不同,解决完全不同的问题。

于 2017-09-05T23:10:48.950 回答
24

C# 扩展方法是staticuse-site,而 Java 的默认方法是virtualdeclaration-site

我相信您希望的是能够将方法“猴子补丁”到您无法控制的类中,但 Java 并没有给您这个(按设计;它被考虑并拒绝了。)

与 C# 方法相比,默认方法的另一个好处是它们可以通过反射发现,实际上从外部看,它们与“常规”接口方法没有任何不同。

C# 的扩展方法相对于 Java 的默认方法的一个优点是,使用 C# 的具体泛型,扩展方法被注入到类型中,而不是中,因此您可以将sum()方法注入到List<int>.

最重要的是,Java 的默认方法和 C# 的扩展方法在哲学上的主要区别在于,C# 允许您将方法注入到您无法控制的类型中(这对开发人员来说肯定很方便),而 Java 的扩展方法是 API 的一流部分它们出现在哪里(它们在界面中声明,它们是反射可发现的,等等)这反映了几个设计原则;库开发人员应该能够保持对其 API 的控制,并且库的使用应该是透明的——x()在类型上调用方法Y应该在任何地方都意味着同样的事情。

于 2014-06-08T03:28:06.907 回答
23

C# 扩展方法只是将扩展类型作为第一个参数的静态方法的语法糖。Java 默认方法完全不同。要模仿 C# 扩展方法,只需编写常用的静态方法。但是,您将没有合成糖;Java 没有这个特性。

Java 默认方法是真正的虚拟方法。例如,它们可以被覆盖。考虑从声明默认方法X的接口继承的类。如果或其任何超类没有声明自己的方法,则将获得. 现在,一个子类可以像通常的方法一样覆盖。因此,默认方法不仅仅是语法糖。它们是其他语言特性无法模仿的方法覆盖和继承机制的真正扩展。Ifoo()Xfoo()Xfoo()IYXX.foo()

默认方法甚至需要特殊的 VM 支持,因此它们甚至不是编译器独有的功能:在类加载期间,必须检查类的层次结构以确定它将继承哪些默认方法。因此,这个决定是在运行时做出的,而不是在编译时做出的。很酷的一点是,当类继承的接口获得新的默认方法时,您不必重新编译该类:VM 将在类加载时将新方法分配给它。

于 2014-06-07T11:03:20.133 回答
8

可以有一些技巧的扩展方法。

你可以试试 Lombok 或 XTend。尽管扩展方法没有随开箱即用的 Java 实现一起提供,但 Lombok 和 XTend 都提供了一个完全可用的解决方案。

Lombok 是一个简单的独立代码处理框架,它使大多数被批评的 Java 特定的麻烦不那么痛苦,包括扩展方法: https ://projectlombok.org/features/experimental/ExtensionMethod.html

Xtend http://www.eclipse.org/xtend/前进了几光年,并实现了一种语言,它结合了现代语言的最佳部分,例如在 Java 和 Java 类型系统之上的 Scala。这允许在同一个项目中用 Xtend 和 Java 实现一些类。Xtend 代码符合有效的 Java 代码,因此不会在后台发生 JVM 魔术。另一方面,如果您只缺少扩展方法,那就有点过分了。

JPropel https://github.com/nicholas22/jpropel-light使用 Lombok 在 Java 中实现 LINQ 样式的扩展方法。可能值得一看:)

于 2016-04-11T23:54:04.880 回答