Java 8 向类添加扩展/默认方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24096421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java 8 add extension/default method to class
提问by Cheetah
I am looking for a java equivalent to the C# extension methods feature. Now I have been reading about Java 8's default methods, but as far as I can see, I can only add these to interfaces...
我正在寻找与 C# 扩展方法功能等效的 Java。现在我一直在阅读 Java 8 的默认方法,但据我所知,我只能将这些添加到接口中......
...is there any language feature that will allow me to write an extension method for a final class that doesn't implement an interface? (I'd rather not have to wrap it...)
...是否有任何语言功能允许我为未实现接口的最终类编写扩展方法?(我宁愿不必包装它......)
采纳答案by gexicide
C# extension methods are just syntactic sugar for static methods that take the extended type as first argument. Java default methods are something completely different. To mimic C# extension methods, just write usual static methods. You will not have the syntatic sugar, however; Java does not have this feature.
C# 扩展方法只是将扩展类型作为第一个参数的静态方法的语法糖。Java 默认方法是完全不同的东西。要模仿 C# 扩展方法,只需编写常用的静态方法。但是,您将没有语法糖;Java没有这个功能。
Java default methods are real virtual methods. For example, they can be overridden. Consider a class X
inheriting from an interface I
that declares a default foo()
method. If X
or any of its super classes declares no own foo()
method, then X
will get the foo()
implementation of I
. Now, a subclass Y
of X
can override X.foo()
like a usual method. Thus, default methods are not only syntactic sugar. They are real extensions of the method overriding and inheritance mechanism that cannot be mimicked by other language features.
Java 默认方法是真正的虚方法。例如,它们可以被覆盖。考虑X
从I
声明默认foo()
方法的接口继承的类。如果X
或其任何超类的声明没有自己的foo()
方法,然后X
将得到foo()
实施I
。现在,子类Y
的X
可以覆盖X.foo()
像通常的方法。因此,默认方法不仅仅是语法糖。它们是其他语言特性无法模仿的方法覆盖和继承机制的真正扩展。
Default methods even require special VM support, so they are not even a compiler only feature: During class loading, the hierarchy of a class has to be checked to determine which default methods it will inherit. Thus, this decision is made at runtime, not at compile time. The cool thing about it is that you do not have to recompile a class when an interface it inherits gets a new default method: The VM will, at class load time, assign that new method to it.
默认方法甚至需要特殊的 VM 支持,因此它们甚至不是编译器独有的功能:在类加载期间,必须检查类的层次结构以确定它将继承哪些默认方法。因此,这个决定是在运行时做出的,而不是在编译时。很酷的一点是,当类继承的接口获得新的默认方法时,您不必重新编译它:VM 将在类加载时将新方法分配给它。
回答by Brian Goetz
C# extension methods are staticand use-site, whereas Java's default methods are virtualand declaration-site.
C# 扩展方法是static和use-site,而 Java 的默认方法是virtual和declaration-site。
What I believe you are hoping for is the ability to "monkey-patch" a method into a class you do not control, but Java does not give you that (by design; it was considered and rejected.)
我相信您希望的是能够将方法“猴子补丁”到您无法控制的类中,但 Java 并没有给您这种能力(按照设计;它被考虑并拒绝了。)
Another benefit of default methods over the C# approach is that they are reflectively discoverable, and in fact from the outside, don't look any different from "regular" interface methods.
默认方法相对于 C# 方法的另一个好处是它们可以反射性地发现,实际上从外部看,它们与“常规”接口方法没有任何不同。
One advantage of C#'s extension methods over Java's default methods is that with C#'s reified generics, extension methods are injected into types, not classes, so you can inject a sum()
method into List<int>
.
C# 的扩展方法相对于 Java 的默认方法的一个优点是,使用 C# 的具体化泛型,扩展方法被注入到类型中,而不是类中,因此您可以将sum()
方法注入到List<int>
.
Above all, the main philosophical difference between Java's default methods and C#'s extension methods is that C# lets you inject methods into types you do not control(which is surely convenient for developers), whereas Java's extension methods are a first-class part of the API in which they appear (they are declared in the interface, they are reflectively discoverable, etc.) This reflects several design principles; library developers should be able to maintain control of their APIs, and library use should be transparent -- calling method x()
on type Y
should mean the same thing everywhere.
最重要的是,Java 的默认方法和 C# 的扩展方法之间的主要哲学区别在于,C# 允许您将方法注入到您无法控制的类型中(这对于开发人员来说肯定很方便),而 Java 的扩展方法是 API 的一流部分它们出现在哪里(它们在接口中声明,它们是反射性的,等等)这反映了几个设计原则;库开发人员应该能够保持对他们的 API 的控制,并且库的使用应该是透明的——x()
在类型上调用方法Y
应该在任何地方都意味着同样的事情。
回答by Gee Bee
It is possible to have extension methods with some tricks.
可以使用一些技巧来扩展方法。
You may give a try to Lombok or XTend. Although extension methods don't come with the out of the box Java implementation, both Lombok and XTend offers a fully working solution.
你可以试试 Lombok 或 XTend。尽管开箱即用的 Java 实现没有附带扩展方法,但 Lombok 和 XTend 都提供了一个完全可行的解决方案。
Lombok is a simple standalone code processing framework, which makes most of the criticized Java specific hassle less painful, including extension methods: https://projectlombok.org/features/experimental/ExtensionMethod.html
Lombok 是一个简单的独立代码处理框架,它使大多数受批评的 Java 特定麻烦变得不那么痛苦,包括扩展方法:https: //projectlombok.org/features/experimental/ExtensionMethod.html
Xtend http://www.eclipse.org/xtend/goes a few lightyears forward, and implements a language which is a combination of the best parts of modern languages such as Scala on top of Java and Java type system. This allows implementing some classes in Xtend and others in Java within the same project. The Xtend code complies to valid Java code, so no JVM magic happens under the hood. On the other hand, it is a little too much if you have only extension methods missing.
Xtend http://www.eclipse.org/xtend/向前迈进了几光年,并实现了一种语言,该语言结合了现代语言(例如 Scala)在 Java 和 Java 类型系统之上的最佳部分。这允许在同一个项目中在 Xtend 中实现一些类,在 Java 中实现其他类。Xtend 代码符合有效的 Java 代码,因此在底层不会发生 JVM 魔法。另一方面,如果您只缺少扩展方法,那就有点太多了。
JPropel https://github.com/nicholas22/jpropel-lightimplements LINQ style extension methods in Java using Lombok. It may worth of a peek :)
JPropel https://github.com/nicholas22/jpropel-light使用 Lombok 在 Java 中实现 LINQ 样式的扩展方法。这可能值得一看:)
回答by Rhyous
Java doesn't have extension methods. Default methods are not extension methods. Let's look at each feature.
Java 没有扩展方法。默认方法不是扩展方法。让我们来看看每个功能。
Java's default methods
Java 的默认方法
Problems solved:
解决的问题:
- Many objects may implement the same interface and all of them may use the same implementation for a method. A base class could solve this issue but only if the interface implementors don't already have a base class as java doesn't support multiple inheritance.
- An API would like to add a method to an interface without breaking the API consumers. Adding a method with a default implementation solves this.
- 许多对象可能实现相同的接口,并且所有对象可能对一个方法使用相同的实现。基类可以解决这个问题,但前提是接口实现者还没有基类,因为 java 不支持多重继承。
- API 希望在不破坏 API 使用者的情况下向接口添加方法。添加具有默认实现的方法可以解决此问题。
Java's default methods are a feature to add a default implementation to an interface. So objects that extend an interface don't have to implement the method, they could just use the default method.
Java 的默认方法是向接口添加默认实现的功能。因此,扩展接口的对象不必实现该方法,它们可以使用默认方法。
interface IA { default public int AddOne(int i) { return i + 1; } }
Any object that implements IA doesn't have to implement AddOne because there is a default method that would be used.
任何实现 IA 的对象都不必实现 AddOne,因为会使用默认方法。
public class MyClass implements IA { /* No AddOne implementation needed */ }
C# lacks this feature and would be greatly improved by adding this feature. (Update: Feature coming in C# 8)
C# 缺少此功能,添加此功能会得到很大改进。(更新:C# 8 中的功能)
C#'s Extension Method
C#的扩展方法
Problems solved:
解决的问题:
- Ability to add methods to sealed classes.
- Ability to add methods to classes from third party libraries without forcing inheritance.
- Ability to add methods to model classes in environments where methods in model classes are not allowed for convention reasons.
- The ability for intellisense to present these methods to you.
- 能够向密封类添加方法。
- 能够在不强制继承的情况下从第三方库向类添加方法。
- 能够在由于约定原因不允许模型类中的方法的环境中向模型类添加方法。
- 智能感知向您展示这些方法的能力。
Example: The type string is a sealed class in C#. You cannot inherit from string as it is sealed. But you can add methods you can call from a string.
示例:字符串类型是 C# 中的密封类。您不能从 string 继承,因为它是密封的。但是您可以添加可以从字符串调用的方法。
var a = "mystring";
a.MyExtensionMethed()
Java lacks this feature and would be greatly improved by adding this feature.
Java 缺少此功能,添加此功能会得到很大改进。
Conclusion
结论
There is nothing even similar about Java's default methods and C#'s extension method features. They are completely different and solve completely different problems.
Java 的默认方法和 C# 的扩展方法功能没有任何相似之处。它们是完全不同的,解决完全不同的问题。