如何使Groovy方法真正受到保护

如何使Groovy方法真正受到保护,groovy,Groovy,试图在groovy中使方法受保护: package com.foo class Foo { protected def getSomething(){ } } 这不起作用,因为groovy默认使几乎所有内容都可见,所以我尝试使用@PackageScope package com.foo import groovy.transform.PackageScope @PacakgeScope class Foo { def getSomething(){ } }

试图在groovy
中使方法受保护

package com.foo

class Foo {

  protected def getSomething(){
  }
}
这不起作用,因为groovy默认使几乎所有内容都可见,所以我尝试使用
@PackageScope

package com.foo

import groovy.transform.PackageScope    

@PacakgeScope
class Foo {

  def getSomething(){
  }
}
这种方法可以工作,但仅当调用者使用
@CompileStatic

   package com.bar

   class Bar {

   @CompileStatic
   static void main(args){
      def f = new Foo()
      println f.getSomething() 
   }
上面抛出的是
IllegalAccessError
,这很好,但是如果没有
@CompileStatic
,则不会生成错误;不太好。我不能强制用户静态编译,所以有没有其他方法可以强制执行
受保护的
方法

来自Groovy Groovy中的Protected与Java中的Protected具有相同的含义,即。 您可以在同一个包中拥有好友,派生类也可以 请参阅受保护的成员


好的,如果
protected
在Groovy中具有相同的含义,但是没有强制执行,那么这不是削弱了它的含义吗?也许我遗漏了什么,

简短的回答:Groovy不强制执行可见性检查

更长的答案 Protected在Java中有一个含义,您肯定知道。我仅为感兴趣的读者提及:

Groovy并不是没有设置相同的修饰符。因此,从Java来看,成员将受到保护,就像Java本身一样。更重要的是,Groovy不在运行时(或编译时)执行可见性检查,甚至可能使用反射来强制实现可访问性。Groovy必须这样做,因为在Groovy中,访问成员的类通常是运行时的一个类。这意味着Groovy必须在运行时模拟可见性检查,但对于这种情况,需要某种类型的“调用来源”,但由于元对象协议缺乏正确传输它的能力,所以Groovy中并不总是可用的


使用@CompileStatic则不同。这里生成了对成员的直接访问。只是它应该已经编译失败了,并且在运行时不会因为Illegaccesserror而失败。

这真是太让人头疼了。我刚刚搜索了“groovy信息隐藏”。外面几乎什么都没有

在Groovy中可能有一些涉及闭包的技术来获取隐藏的信息。但我只是做了一些实验,并找到了一种可能有用的方法,希望能将
@CompileStatic
。它涉及使用一个内部类,并结合从
抽象类
类生成子类,如果非法尝试绕过工厂方法,则引发异常。事实上,这是一个相当复杂的过程

更重要的是,经过仔细检查,我发现即使这样也不起作用

到目前为止,我发现的唯一方法就是这样一种uber黑客,我甚至羞于提及它:一种涉及检查堆栈跟踪的技术

我很清楚,实际上
@CompileStatic
更多的是关于类型检查的强制执行,而不是关于信息隐藏:它以一种更强大的注释版本
@TypeChecked
的方式被覆盖

在Python中,有一种约定(我假设仍然使用),即为那些“被视为私有”的字段指定一种特殊的命名约定,即名称以双下划线开头。但我在Groovy中没有看到类似的情况


布洛赫在他的优秀著作《有效的Java》中,给出了信息隐藏非常重要的许多合理理由。当然,现在大家都知道,即使在Java中,所有这些都是脆弱的,可以通过反射技术来破解。但是我想听听一个Groovy uber极客对您的问题提出的看法…

Groovy强制执行
私有
,但是
公共
受保护
的行为似乎是一样的。我猜
@CompileStatic
是唯一的选项,请注意,Groovy没有像Java那样强制私有。如果您有一个子类实例,则无法访问超类的私有成员,但仅此而已。如果您用一个私有字段定义一个类Foo,并访问Foo实例(不是Foo的子类)上的字段,那么在Groovy中您可以访问该字段。@blackdrag感谢您指出了这个微妙之处。我想,显而易见的“反应”是将所有具有此类私有字段的类抽象化。。。