Как сделать Groovy-метод действительно защищенным

Попытка сделать метод в заводной protected:

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ошибка не генерируется; не так приятно Я не могу заставить пользователей компилировать статически, так есть ли альтернатива protected методы?

Из Groovy Документация

Защищенный в Groovy имеет то же значение, что и защищенный в Java, то есть вы можете иметь друзей в одном пакете, а производные классы также могут видеть защищенные члены.

Хорошо, если protected имеет то же значение в Groovy, но не применяется как таковое, не разрушает ли это значение? Может быть, я что-то упустил,

2 ответа

Краткий ответ: Groovy не требует проверки видимости.

Более длинный ответ Защищенный имеет значение в Java, что вы наверняка знаете. Я упоминаю это только для заинтересованного читателя: http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html

Нельзя сказать, что Groovy не устанавливает тот же модификатор. Таким образом, как видно из Java, член будет защищен так же, как и в самой Java. Более того, Groovy не выполняет проверку видимости во время выполнения (или во время компиляции) и может даже использовать отражение для форсирования доступности. Groovy должен сделать это, потому что в целом в Groovy класс, обращающийся к члену, является одним из времени выполнения. Это означает, что Groovy придется эмулировать проверки видимости во время выполнения, но для этого требуется какой-то "источник вызова", но он не всегда доступен в Groovy из-за отсутствия в протоколе метаобъекта возможности его правильной передачи.

Использование @CompileStatic вещи разные. Здесь прямой доступ к члену производится. Только он должен был уже потерпеть неудачу при компиляции и не потерпеть неудачу во время выполнения с IllegalAccessError.

Это довольно царапает голову. Я только что выполнил поиск по "скрытой информации". Там почти ничего нет!

Там могут быть методы, связанные с замыканиями для получения сокрытия информации в Groovy. Но я просто провел несколько экспериментов и нашел способ, надеюсь, навязать @CompileStatic которые могут быть полезны. Он включает в себя использование внутреннего класса в сочетании с подклассами из abstract класса, и выдает исключение, если предпринята недопустимая попытка обойти фабричный метод. На самом деле это был настоящий взлом.

Более того, при ближайшем рассмотрении я обнаружил, что даже это не сработало.

Единственный способ, который я нашел до сих пор, - это такой хакерский взлом, что мне стыдно даже упоминать об этом: техника, включающая проверку трассировки стека.

О возвращении с Groovy In Action 2nd Ed. мне ясно, что на самом деле @CompileStatic гораздо больше о применении проверки типов, чем о скрытии информации: он описан таким образом, что выглядит как более мощная версия аннотации @TypeChecked,

В Python есть соглашение, которое, я полагаю, до сих пор используется, дает специальным соглашениям об именах для полей, которые должны рассматриваться как "частные", а именно, чтобы имя начиналось с двойного подчеркивания. Но я ничего такого не видел в Groovy.

Блох в своей превосходной книге " Эффективная Java" приводит множество веских причин, по которым сокрытие информации очень важно. Конечно, к настоящему времени хорошо известно, что даже в Java все это ненадежно и может быть взломано методами отражения. Но я хотел бы услышать от Groovy uber-geek их мнение по вопросу, поднятому вашим вопросом...

Другие вопросы по тегам