有人会解释我什么时候想使用 Groovy Traits vs. Mixins (@Mixin) vs. 代表 (@Delegate)?也许一些权衡和设计问题会有所帮助。
它们似乎都允许重用多个“类”行为。谢谢。 :-)
这个 SO 线程也很有帮助:Difference between @Delegate and @Mixin AST transformations in Groovy
最佳答案
我同意,它们似乎都允许重用多个“类”行为。不过还是有区别的
了解这些可能会帮助您做出决定。
在提供每个功能的简要总结/亮点和合适的示例之前
用法,让我们总结一下每个的结论。
结论/典型用法:
实际执行。让你成就composition over inheritance .
其中之一是在 Java 类中可以看到添加的方法。
现在,让我们更详细地研究每一个。
@代表
在许多情况下,继承被过度使用。也就是说,它经常被不当使用。 Java 中的经典示例是
扩展输入流、读取器或集合类.. 对于大多数这些,使用继承太
与实现紧密结合。也就是说,实际的实现是这样编写的
公共(public)方法实际上使用另一个。如果您覆盖两者,并调用
super
,那么你可能会不想要副作用。如果实现在更高版本中发生变化,那么您将不得不更新您对
它也是。
相反,您应该努力使用 composition over inheritance .
例如,一个对添加到列表中的元素进行计数的计数列表:
class CountingList<E> {
int counter = 0
@Delegate LinkedList<E> list = new LinkedList<>()
boolean addAll(Collection<? extends E> c) {
counter += c.size()
list.addAll(c)
}
boolean addAll(int index, Collection<? extends E> c) {
counter += c.size()
list.addAll(index, c)
}
// more add methods with counter updates
}
在本例中,
@Delegate
删除所有公共(public)方法的所有繁琐的样板代码想要保持“原样”,即添加了简单地将调用转发到基础列表的方法。此外,
CountingList
与实现分开,这样您就不必关心其中之一方法是通过调用另一个来实现的。在上面的例子中,情况确实如此,因为
LinkedList.add(Collection)
电话LinkedList.add(int, Collection)
,所以它不会那么简单使用继承来实现。
概括:
@Delegate
s 到一个类(class)。CountingList
)不是委托(delegate)类的实例。CountingList
不是 LinkedList
的实例. @Mixin
@Mixin
由于即将推出的特征支持,转换将在 groovy 2.3 中被弃用。这提供了一个暗示所有可能与
@Mixin
有关的事情, 应该可以用 trait 来代替。根据我的经验,
@Mixin
真是喜忧参半。 :)核心开发人员承认,它充满了“难以解决的”错误。这并不是说它已经
“没用”,远非如此。但是如果你有机会使用(或等待)groovy 2.3,那么你应该使用
性状代替。
AST 转换所做的只是将一个类中的方法添加到另一个类中。例如:
class First {
String hello(String name) { "Hello $name!" }
}
@Mixin(First)
class Second {
// more methods
}
assert new Second().hello('Vahid') == 'Hello Vahid!'
概括:
Second
不是 First
的实例运行时混入
运行时 mixins 和
@Mixin
变换完全不同,它们解决不同的用例并被使用在完全不同的情况下。由于它们具有相同的名称,因此很容易将一个与另一个混淆,或者
认为他们是一回事。然而,运行时 mixins 在 groovy 2.3 中并未被弃用。
我倾向于将运行时 mixin 视为向现有类(例如 JDK 中的任何类)添加方法的方式。
这是 Groovy 用来向 JDK 添加额外方法的机制。
例子:
class MyStringExtension {
public static String hello(String self) {
return "Hello $self!"
}
}
String.mixin(MyStringExtension)
assert "Vahid".hello() == 'Hello Vahid!'
Groovy 也有不错的 extension module功能,您不需要手动执行 mixin,而是
只要 groovy 在类路径中的正确位置找到模块描述符,它就会为您做这件事。
概括:
性状
特性是 groovy 2.3 的新特性。
我倾向于将这些特征视为介于熟悉的界面和类之间的东西。类似于“轻量级”的东西
类(class)。它们在文档中被称为“具有默认实现和状态的接口(interface)”。
性状类似于
@Mixin
转换它们取代,但它们也更强大。首先,他们更明确。 trait 不能直接实例化,就像接口(interface)一样,它们需要一个实现
类(class)。一个类可以实现许多特征。
一个简单的例子:
trait Name {
abstract String name()
String myNameIs() { "My name is ${name()}!" }
}
trait Age {
int age() { 42 }
}
class Person implements Name, Age {
String name() { 'Vahid' }
}
def p = new Person()
assert p.myNameIs() == 'My name is Vahid!'
assert p.age() == 42
assert p instanceof Name
assert p instanceof Age
特征和@Mixin 之间的直接区别在于
trait
是语言关键字,而不是 AST 转换。此外,它可以包含需要由类实现的抽象方法。此外,一个类可以实现
几个特点。实现 trait 的类是该 trait 的一个实例。
概括:
关于design-patterns - Groovy 中@Delegate、@Mixin 和 Traits 的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23121890/