我正在寻找与 C# 扩展方法功能等效的 java。现在我一直在阅读 Java 8 的默认方法,但据我所知,我只能将这些添加到接口中......
...是否有任何语言功能可以让我为不实现接口的最终类编写扩展方法?(我宁愿不必包装它......)
我正在寻找与 C# 扩展方法功能等效的 java。现在我一直在阅读 Java 8 的默认方法,但据我所知,我只能将这些添加到接口中......
...是否有任何语言功能可以让我为不实现接口的最终类编写扩展方法?(我宁愿不必包装它......)
Java 没有扩展方法。默认方法不是扩展方法。让我们看看每个功能。
Java 和 C# 都支持此功能
解决的问题:
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# 中的密封类。您不能从字符串继承,因为它是密封的。但是您可以添加可以从字符串调用的方法。
var a = "mystring";
a.MyExtensionMethed()
Java 缺少这个特性,并且通过添加这个特性会得到很大的改进。
Java 的默认方法和 C# 的扩展方法特性没有任何相似之处。它们完全不同,解决完全不同的问题。
C# 扩展方法是static和use-site,而 Java 的默认方法是virtual和declaration-site。
我相信您希望的是能够将方法“猴子补丁”到您无法控制的类中,但 Java 并没有给您这个(按设计;它被考虑并拒绝了。)
与 C# 方法相比,默认方法的另一个好处是它们可以通过反射发现,实际上从外部看,它们与“常规”接口方法没有任何不同。
C# 的扩展方法相对于 Java 的默认方法的一个优点是,使用 C# 的具体泛型,扩展方法被注入到类型中,而不是类中,因此您可以将sum()
方法注入到List<int>
.
最重要的是,Java 的默认方法和 C# 的扩展方法在哲学上的主要区别在于,C# 允许您将方法注入到您无法控制的类型中(这对开发人员来说肯定很方便),而 Java 的扩展方法是 API 的一流部分它们出现在哪里(它们在界面中声明,它们是反射可发现的,等等)这反映了几个设计原则;库开发人员应该能够保持对其 API 的控制,并且库的使用应该是透明的——x()
在类型上调用方法Y
应该在任何地方都意味着同样的事情。
C# 扩展方法只是将扩展类型作为第一个参数的静态方法的语法糖。Java 默认方法完全不同。要模仿 C# 扩展方法,只需编写常用的静态方法。但是,您将没有合成糖;Java 没有这个特性。
Java 默认方法是真正的虚拟方法。例如,它们可以被覆盖。考虑从声明默认方法X
的接口继承的类。如果或其任何超类没有声明自己的方法,则将获得. 现在,一个子类可以像通常的方法一样覆盖。因此,默认方法不仅仅是语法糖。它们是其他语言特性无法模仿的方法覆盖和继承机制的真正扩展。I
foo()
X
foo()
X
foo()
I
Y
X
X.foo()
默认方法甚至需要特殊的 VM 支持,因此它们甚至不是编译器独有的功能:在类加载期间,必须检查类的层次结构以确定它将继承哪些默认方法。因此,这个决定是在运行时做出的,而不是在编译时做出的。很酷的一点是,当类继承的接口获得新的默认方法时,您不必重新编译该类:VM 将在类加载时将新方法分配给它。
可以有一些技巧的扩展方法。
你可以试试 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 样式的扩展方法。可能值得一看:)