Vah*_*deh 56 groovy delegates design-patterns traits mixins
有人会解释我什么时候想要使用Groovy Traits vs. Mixins(@Mixin)与代表(@Delegate)?也许一些权衡和设计问题会有所帮助.
它们似乎都允许重复使用多个"类"行为.谢谢.:-)
这个SO线程也很有帮助:Groovy中@Delegate和@Mixin AST转换之间的区别
Ste*_*nar 116
我同意,他们似乎都允许重复使用多个"类"的行为.但是,存在差异,理解这些可能有助于您做出决定.
在提供每个功能的简要摘要/重点和适当用法的示例之前,让我们总结每个功能的结论.
结论/典型用法:
现在,让我们更详细地研究每一个.
@代表
在许多情况下,继承被过度使用.也就是说,它经常被不正确地使用.Java中的经典示例是扩展输入流,读取器或集合类.对于大多数这些,使用继承与实现过于紧密耦合.也就是说,编写实际的实现,以便其中一个公共方法实际使用另一个.如果你同时覆盖两个,并且你打电话super,那么你可能会得到不必要的副作用.如果实现在更高版本中更改,那么您还必须更新对它的处理.
相反,你应该努力使用组合而不是继承.
例如,计算添加到列表中的元素的计数列表:
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
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,@Delegate删除了您希望"按原样"保留的所有公共方法的所有繁琐的样板代码,即添加了简单地将调用转发到基础列表的方法.此外,CountingList它与实现分离,因此您无需关心是否通过调用另一个来实现这些方法之一.在上面的例子中,实际情况就是这样,因为
LinkedList.add(Collection)调用LinkedList.add(int, Collection),所以使用继承实现它并不是那么简单.
摘要:
@Delegates 添加到一个类中.
CountingList在上面的示例中)不是委托类的实例.
CountingList不是一个实例LinkedList.@Mixin
该@Mixin转换将使用Groovy 2.3被弃用,由于即将到来的特性支持.这提供了一个提示,即可以做的所有事情都@Mixin应该与特征相关.
根据我的经验,这@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!'
Run Code Online (Sandbox Code Playgroud)
摘要:
Second不是一个实例First运行时混合
运行时混合和@Mixin变换是完全不同的,它们解决了不同的用例,并且在完全不同的情况下使用.由于它们具有相同的名称,因此很容易将一个与另一个混淆,或者认为它们是同一个.但是,在groovy 2.3 中不会弃用运行时混合.
我倾向于将运行时mixins视为向现有类添加方法的方法,例如JDK中的任何类.这是Groovy用于向JDK添加额外方法的机制.
例:
class MyStringExtension {
public static String hello(String self) {
return "Hello $self!"
}
}
String.mixin(MyStringExtension)
assert "Vahid".hello() == 'Hello Vahid!'
Run Code Online (Sandbox Code Playgroud)
Groovy还有一个很好的扩展模块功能,你不需要手动执行mixin,只要它在类路径中的正确位置找到模块描述符,groovy就会为你做.
摘要:
性状
特征是groovy 2.3的新特征.
我倾向于将这些特征视为熟悉的界面和类之间的东西.类似于"轻量级"类的东西.它们在文档中被称为"具有默认实现和状态的接口".
特征与@Mixin它们取代的变换类似,但它们也更强大.对于初学者来说,他们的定义要明确得多.特征不能直接实例化,就像接口一样,它们需要一个实现类.一个类可以实现许多特征.
一个简单的例子:
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
Run Code Online (Sandbox Code Playgroud)
特征和@Mixin之间的直接区别在于它trait是一个语言关键字,而不是AST转换.此外,它可以包含需要由类实现的抽象方法.此外,一个类可以实现几个特征.实现特征的类是该特征的一个实例.
摘要:
| 归档时间: |
|
| 查看次数: |
11692 次 |
| 最近记录: |