虽然web上有丰富的资源赞美Groovy的无数元编程功能,但我还没有找到任何关于实际使用这些特性的全面的“最佳实践”指南。
除了典型的警告词过度使用警告外,我所读到的最具体的建议是在可能的情况下使用类别来支持增加元类(这实际上只是加强“有限范围”这一古老成语的另一种方式)。
对于我的琐碎项目来说,常识已经足够了,但随着我处理更多雄心勃勃的任务,我越来越担心从潜在的糟糕/不一致的先例中建立起来。
因此,我非常感谢Groovy的任何建议、资源或具体示例(甚至是语言不可知论者--我在Ruby方面的短暂经验也让我同样渴望)元编程最佳实践。
为了澄清这个主题,我将提供一个(高度)简化的Rational项目,它可以以几种不同的方式使用元编程:
@Immutable class Rational{
int num, den
Rational multiply(Integer v){
new Rational(num:num*v, den:den)
}
}
assert new Rational(num:1, den:2) * 3 == new Rational(num:3, den:2)然而,尝试3*new Rational(num:1, den:2)显然会产生一个MissingMethodException。
添加通信属性的最简单、也可以说是最不脆弱的方法是在Rational类中使用静态初始化块:
static {
Integer.metaClass.multiply = {Rational fraction -> fraction*delegate}
}
...
assert 3*new Rational(num:1, den:2) == new Rational(num:3, den:2)但这实际上是全球性的,而且相当僵化。
一种更多用途,或许更有组织的方法是采用某种可选的引导方式:
class BootStrap{
static void initialize(){
Integer.metaClass.multiply = {Rational fraction -> fraction*delegate}
}
}现在我们可以选择启用我们希望拥有的特性。然而,这可能会导致各种形式的依赖问题。
还有分类..。安全明确,但不完全方便:
@Category(Integer) class RationalCategory{
Rational multiply(Rational frac){
frac*this
}
}
use(RationalCategory){
assert 3*new Rational(num:1, den:2) == new Rational(num:3, den:2)
}通常,当我添加新的行为时,我会修改元类,但是当我改变现有的行为时,我会使用类别。例如,将除法运算符重写为生成一个分数,最好包含在一个类别中。因此,解决方案1或2将是“可接受的”,因为我只是将行为附加到Integer类中,而不是改变典型的用法。
有人同意/不同意这种看法吗?或者可能知道一些更好的方法?(我在这里省略了混合器,我知道。)
发布于 2010-12-08 07:24:24
有一章讨论了Groovy中的元编程,它很好地涵盖了这个主题。一定要得到第二版(印刷版还没有,但你可以得到一个电子格式的早期访问版本),因为第一版非常过时,特别是在元编程的主题上。
https://stackoverflow.com/questions/4380929
复制相似问题