Скрытие информации в Groovy (с использованием замыканий «соглашения об именах») - PullRequest
0 голосов
/ 12 июня 2018

Это следует из моей неудачной попытки найти ответ на этот вопрос от 2014 года.

Мне не ясно, могут ли в Groovy существовать какие-то методы для использования замыканий,в частности, чтобы скрыть информацию.Все, что я могу сказать, это то, что если информация о таких методах существует, то это точная иллюстрация «сокрытия информации»: я не могу ее найти!

Но, если мне кажется, что мое понимание сейчас таково,Абсолютно нулевая попытка скрыть информацию (или сделать вид, как в Java - с учетом техники отражения) когда-либо предпринималась.Похоже, что это из-за дизайна, но также из-за требований динамического характера Groovy.Кажется, например, что @CompileStatic, упомянутый в упомянутом вопросе, больше относится к проверке типов, чем к чему-либо еще.

Но в Python, например, есть соглашение (я полагаю, все еще используется)чтобы «поля, которые должны рассматриваться как частные», начинались с двойного подчеркивания.Я никогда не слышал, чтобы кто-то говорил об этом в связи с Groovy.

Разве это не сокрытие информации и не инкапсуляция, или, по крайней мере, соглашения, поощряющие дисциплинированное использование «интимного состояния» объектов, хорошие вещи?Любые эксперты Groovy хотят прокомментировать?

позже

Даггетт дал ответ, который интересен в некоторых отношениях, но не совсем то, что я имелв уме.Учтите это:

class Main {
    static main( args ) {
        def sm = new SecurityManager()
        System.setSecurityManager( sm )
        println new Bob().doSomethingProtected()
    }
}


class Bob {
    public doSomethingPublic() {
        "public"
    }
    private doSomethingPrivate() {
        "private"
    }
    protected doSomethingProtected() {
        "protected"
    }
}

... какой бы из этих методов Bob ни вызывался, он будет проходить с не установленным SecurityManager, но завершится неудачей с его установленным.Также не имеет значения, в каком пакете он находится. Также не имеет значения, находится ли Bob в подпакете (например), с @PackageScope: только если Main.main задано @CompileStatic, это поможет (см. ссылочный вопрос).Мне также непонятно, что именно вы можете сделать с таким набором SecurityManager: возможно ли каким-то образом принудительно применить private или protected (или пакетно-закрытый)?На данный момент я просто не знаю, и мне придется расследовать.

Что касается другого предложения, оно интригует, но на самом деле не отрицает "видимость", как было предложено.Вам также необходимо включить следующий метод в класс A:

def getI() {
    throw new Exception()
}

После этого, да, доступ к любому другому классу, независимо от того, находится ли он в том же пакете, или нет, итакже эти "частные" элементы даже не видны другим объектам того же класса (! - в отличие от Java).В этом смысле это действительно обеспечивает очень драконовскую конфиденциальность.Но для меня это тоже немного взломать.Я не совсем уверен насчет этого GroovyObjectSupport класса или того, что он делает, и мне придется его исследовать.Наконец, нет смысла давать этим полям модификатор private.Как я уже сказал, ЕДИНСТВЕННАЯ функция private в Groovy состоит в том, чтобы запретить видимость этих полей для подклассов класса Даггетта A здесь.

Имея только абсолютный выбор между супер-драконианской и хакерской "приватной"", или" неограниченно публичный ", явно представляет собой значительное" обнищание "выбора видимости по сравнению с Java, где у вас есть не только protected, но и частный пакет (предмет, да да да, конечно, использование отражения...) и где private поля видны другим объектам того же класса.

1 Ответ

0 голосов
/ 14 июня 2018

SecurityManager

не запускайте следующий код из GroovyConsole.только из командной строки groovy.

def sm = new SecurityManager()
System.setSecurityManager(sm)
//without previous lines the following code will run successfully
println new ByteArrayOutputStream().buf

это вызовет следующее исключение

Caught: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:109)
        at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:131)
Caused by: java.lang.ExceptionInInitializerError
        at groovy.ui.GroovyMain.run(GroovyMain.java:397)
        at groovy.ui.GroovyMain.process(GroovyMain.java:370)
        at groovy.ui.GroovyMain.processArgs(GroovyMain.java:129)
        at groovy.ui.GroovyMain.main(GroovyMain.java:109)
        ... 6 more
Caused by: java.security.AccessControlException: access denied ("java.util.logging.LoggingPermission" "control")
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
        at java.security.AccessController.checkPermission(AccessController.java:884)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        at java.util.logging.LogManager.checkPermission(LogManager.java:1586)
        at java.util.logging.Logger.checkPermission(Logger.java:422)
        at java.util.logging.Logger.setUseParentHandlers(Logger.java:1799)
        at org.codehaus.groovy.runtime.StackTraceUtils.<clinit>(StackTraceUtils.java:57)
        ... 10 more

контроль доступа с getProperty & setProperty

class A extends GroovyObjectSupport{
    private int i=555
    private int j=666
    def f(){
        println "i=$i j=$j"
    }
    Object getProperty(String name){
        if(name in ['i'])throw new Exception("Access to property `$name` is denied")
        return super.getProperty(name)
    }
}
def a=new A()
a.f()
println "a.j = ${a.j}"
println "a.i = ${a.i}"

это позволит получить доступ к члену j, но не к члену i вне класса.

вывод:

i=555 j=666
a.j = 666
Exception thrown

java.lang.Exception: Access to property `i` is denied
  ...
...