Groovy 탐색의 메타클래스 함정 기어오르기

이틀 동안 그루비 메타클래스의 함정에 빠져 겨우 기어나왔다.
이 문제를 분명히 말하기 위해서 먼저 몇 줄의 테스트 코드를 보았다
 
    void testMetaClass() {
        def domain = new Domain()
        domain.metaClass.p = 'v1'
        assertEquals 'v1', domain.p

        domain.p = 'v2'
        assertEquals 'v2', domain.p

        domain.metaClass.p = 'v3'
        assertEquals 'v2', domain.p
    }

이것은 이미 통과된 테스트이다.
-------------------------------------------------------
Running 1 unit test...
Running test com.grs.GroovyMetaClassTests...null
Empty test suite.
PASSED
Tests Completed in 359ms ...
-------------------------------------------------------

Groovy 테스트 코드의 마지막 두 줄을 확인합니다.
domain.metaClass.p = 'v3'
assertEquals 'v2', domain.p

언뜻 보기엔 답답하다: 집행
domain.metaClass.p = 'v3'

그 다음에 왜domain.p의 값은 여전히'v2'입니까?이것이 바로 내가 함정이라고 부르는 곳이다.보아하니 Groovy에는 이런 규칙이 있는 것 같다. Groovy Object에서 처음으로 통과한 것이다
domain.metaClass.aProperty = aValue 

의 방식으로domain에 aProperty를 주입한 후 다시 실행합니다
domain.metaClass.aProperty = yetAnotherValue 

domain을 변경할 수 없습니다.aProperty,
domain.aProperty = yetAnotherValue 

성공적으로 변경할 수 있습니다.
 
이 함정에서 벗어나서 우리는 이 문제를 어떻게 해결해야 하는지를 보았다. 나는 어떻게 aProperty가 이미 주입되었는지 알 수 있습니까?다시 말하면, 내가 마땅히 써야 한다는 것을 어떻게 알았겠는가
domain.metaClass.aProperty = yetAnotherValue

그래도
domain.aProperty = yetAnotherValue

네?
 
나는 두 개의 워크맨이 있다.
1. try를 통해...catch...검사하다
class GroovyFieldAccessor {
  static void set(String fieldName, Object obj, Object v) {
    def metaPropAlreadyInjected = true
    try {
        if(obj."$fieldName") {} // do nothing but check if d."$fieldName" will throw an exception.
    } catch(x) {metaPropAlreadyInjected = false}
    if(metaPropAlreadyInjected) {
        obj."$fieldName" = v
    } else {
        obj.metaClass."$fieldName" = v
    }

  }
}

2. 매번 두 마디씩 함께 쓴다.
obj.metaClass."$fieldName" = v
obj."$fieldName" = v

만전을 기하다.
 
개인은 후자를 비교적 좋아한다. 왜냐하면 그것은 두 줄로 매우 간결하기 때문이다.

좋은 웹페이지 즐겨찾기