【问题标题】:Looking for solution for Groovy @Mixin not to break encapsulation为 Groovy @Mixin 寻找不破坏封装的解决方案
【发布时间】:2012-11-11 19:30:31
【问题描述】:

我想在 Groovy 中使用 @Mixin 注释,它完全符合我的要求,除了它还混合了私有方法和字段。

class A {
def private fooA() {
        println("A")
    }
}

@Mixin(A)
class B {
    def fooB() {
        println("B")
   }
}

如果我现在运行这段代码

static main(args)
{
    def b = new B()
    println(b.fooA())
    B.metaClass.fooA = {throw new MissingMethodException()};
    println(b.fooA())
}

它首先调用私有方法 A.fooA 并打印“A”。然后该私有方法被删除,并且不能被 A 类中混合的客户端 B 调用。这就是我希望事情从一开始就是这样的方式。

我现在的问题是如何以通用方式实现这一目标?我可以扩展@Mixin 注释。问题是我是 Groovy 的新手,关于如何编写 AST 转换的信息真的不多。新的 Groovy in Action 书有一整章的内容尚未出版。

我可以改用@Delegate,但是我必须为委托给的类声明一个变量。这不是我想要的。我希望我可以告诉开发人员使用我的东西简单地用@Mixin 注释他的类,以便混合我的东西,就是这样。而且我可以确定我的类的私有方法和字段不能被用户破坏混入的类的内部代码调用。

有没有人暗示我应该朝哪个方向努力? 谢谢,奥利弗

【问题讨论】:

    标签: groovy metaprogramming abstract-syntax-tree mixins


    【解决方案1】:

    我认为您发现了一些不是 Groovy 重点的东西。对隐藏私人成员的支持一般有issues

    在您的具体情况下,您可能遇到了一个新错误(?)。仔细观察,看起来@Mixin 的 AST 转换调用了到达MixinInMetaClass.mixinClassesToMetaClass() 的代码。这是在努力不将非公共方法复制到目标元类(您的 B 类的元类);它们没有出现在您的 b.metaClass 的方法列表中,所以这似乎是正确的。

    调用b.fooA() 将起作用(不知何故),直到您尝试使用不存在的属性或在 b 上调用不存在的方法。 (或致电b.metaClass.initialize())。然后您将收到缺少fooA() 的投诉。

    所以,我不确定我是否会投入太多精力来尝试让访问修饰符与 Groovy 一起工作,但如果你继续走这条路,我认为你可能需要为类编写一些初始化代码就像您在上面所做的那样,或致电initialize() 或如上所述的不良财产。您可以尝试将其中的一些代码放在您自己的ASTTransformation 类中,但我没有尝试过。您可以获取source 并查看org.codehaus.groovy.ast.MixinASTTransformation

    【讨论】:

    • 嗨,布赖恩,感谢您的回答。好吧,当输入“f”后IDE(我使用IDEA)中弹出自动完成选择列表时。私有方法 fooA 未列为可选选项(但 fooB 是)。任何仍在 B 实例上调用 fooA 的开发人员之前都受到过警告。也许这已经足够好了。最终,我太习惯于我以前的“所有类型安全”的世界;-)。
    猜你喜欢
    • 2014-07-20
    • 2017-07-27
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多