2013-04-24 2 views
3

클로저가 구현되는 수퍼 클래스 대신 실제 클래스로 실행되어 일부 변수가 표시되지 않을 때 중단된다는 인상을받습니다 (예 : private in 수퍼 클래스). 예를groovy : 수퍼 클래스 클로저의 변수 범위 (MissingPropertyException)

package comp.ds.GenericTest2 

import groovy.transform.CompileStatic 

@CompileStatic 
class ClosureScopeC { 
     private List<String> list = new ArrayList<String>() 
     private int accessThisPrivateVariable = 0; 

     void add(String a) { 
       list.add(a) 
       println("before ${accessThisPrivateVariable} ${this.class.name}") 
       // do something with a closure 
       list.each {String it -> 
         if (it == a) { 
           // accessThisPrivateVariable belongs to ClosureScopeC 
           accessThisPrivateVariable++ 
         } 
       } 
       println("after ${accessThisPrivateVariable}") 
     } 
} 

// this works fine 
a = new ClosureScopeC() 
a.add("abc") 
a.add("abc") 

// child class 
class ClosureScopeD extends ClosureScopeC { 
     void doSomething(String obj) { 
       this.add(obj) 
     } 
} 

b = new ClosureScopeD() 

// THIS THROWS groovy.lang.MissingPropertyException: No such property: accessThisPrivateVariable for class: comp.ds.GenericTest2.ClosureScopeD 
b.doSomething("abc") 

마지막 줄에 대한

는 MissingPropertyException를 던졌습니다 : 자식 클래스는 "accessThisPrivateVariable을"사용 "각"폐쇄을 실행하는 슈퍼 클래스의 "추가"메소드를 호출합니다.

저는 groovy에 익숙하지 않으므로 이것을 할 수있는 쉬운 방법이 있어야한다고 생각합니다. 그렇지 않으면 클로저가 수퍼 클래스에서 수행 한 개인 구현의 캡슐화를 완전히 깨뜨린 것처럼 보이기 때문입니다.

+0

다른 질문과 마찬가지로, 이것은 Groovy 사용자 메일 링리스트에서 더 잘 묻습니다. –

+0

Ok, 감사합니다. Tim, 알겠습니다. – user1070984

답변

0

2.1.3 내가이 얼마나 멋져요 변수 범위의 작업을 설명하는 좋은 참고 것으로 확인하고 상황에 맞는 내가 끝내 사용하고

(슈퍼 클래스 구현은 자신의 개인 변수를 참조) 매우 일반적인 필요 : Closure in groovy cannot use private field when called from extending class

위의 링크에서 알 수 있듯이 요 u가 accessThisPrivateVariable을 private로 선언했다면 Groovy는 변수에 대한 getter/setter를 자동으로 생성하지 않습니다. Java에서도 개인 변수는 하위 클래스에서 직접 액세스 할 수 없습니다.

package com.test 
import groovy.transform.CompileStatic 

@CompileStatic 
class ClosureScopeC { 
    private List<String> list = new ArrayList<String>() 
    private int accessThisPrivateVariable = 0; 

    int getAccessThisPrivateVariable() { accessThisPrivateVariable } 
    void setAccessThisPrivateVariable(int value){this.accessThisPrivateVariable = value} 

    void add(String a) { 
     list.add(a) 
     println("before ${accessThisPrivateVariable} ${this.class.name}") 
     // do something with a closure 
     list.each {String it -> 
      if (it == a) { 
       // accessThisPrivateVariable belongs to ClosureScopeC 
       accessThisPrivateVariable++ 
      } 
     } 
     println("after ${accessThisPrivateVariable}") 
    } 
} 

// this works fine 
a = new ClosureScopeC() 
a.add("abc") 
a.add("abc") 

// child class 
class ClosureScopeD extends ClosureScopeC { 
    void doSomething(String obj) { 
     super.add(obj) 
    } 
} 

b = new ClosureScopeD() 
b.doSomething("abc") 

그냥 액세스 한정자을 (정말 속성을 이름을 변경한다), 간단한 방법이있다 보호에 있으므로 하위 : 명시 적으로 게터/세터를 추가하는 코드를 변경

이 문제를 해결 -class는 문제 해결 된 속성에 대한 액세스 권한을가집니다.

protected int accessThisProtectedVariable 

Groovy가 캡슐화를 깨뜨렸을 가능성이 있다는 귀하의 진술을 명확히하기 위해 안심하십시오.

필드를 비공개로 선언하면 Groovy는 공용 getter/setter의 자동 생성을 의도적으로 중단하여 캡슐화를 보존합니다. 일단 비공개가되면, 하위 클래스 (보호 된) 또는 모든 클래스의 객체 (공용)가 명시 적으로 메소드를 추가하여 필드에 액세스 할 수있는 방법 또는 방법이 있는지 여부를 완전히 제어 할 수 있습니다.

Groovy는 항상 코드가 필드를 참조 할 때 getter 또는 setter를 호출한다는 것을 기억하십시오. 그래서, 성명 같은 :

def f = obj.someField 

실제로 obj.getSomeField() 메소드를 호출합니다. 마찬가지로 :

obj.someField = 5 

obj.setSomeField(5) 메소드를 호출한다.

관련 문제