목차

Groovy Meta Programming

GroovyInterceptable

MetaClass Interception

YourClass.metaClass.invokeMethod = { String methodName, methodArgs ->
  //구현
  // 객체 자신을 가리킬 때는 delegate 를 사용한다. closure 이기 때문.
  // 존재하지 않는 메소드 호출을 metaClass.invokeMissingMethod() 에 위임시킬 수 있다.
  // invokeMissingMethod는 다시 missingMethod()에 위임한다.
}

ExpandoMetaClass

// 아래처럼 metaClass에 메소드를 추가해줘야 metaClass 구현체가 ExpandoMetaClass로 변경됨.
Integer.metaClass.invokeMethod = { String name, args -> /* */ }
println Integer.metaClass.getClass().name // ExpandoMetaClass

대량의 메소드 추가 기법

Integer.metaClass {
    // 메소드 추가
    daysFromNow = { ->
        Calendar today = Calendar.instance
        today.add(Calendar.DAY_OF_MONTH, delegate)
        today.time
    }
 
    // 프라퍼티 추가. 괄호없이 호출가능.
    getDaysFromNow = { ->
        Calendar today = Calendar.instance
        today.add(Calendar.DAY_OF_MONTH, delegate)
        today.time
    }
 
    // static method 추가
    'static' {
        isEven = { val -> val % 2 == 0 }
    }
 
    // 생성자 추가
    constructor = { Calendar calendar ->
        new Integer(calendar.get(Calendar.DAY_OF_YEAR))
    }
 
    constructor = { int val ->
        println "Intercepting constructor call"
        constructor = Integer.class.getConstructor(Integer.TYPE)
        constructor.newInstance(val)
    }
}
 
println 5.daysFromNow()
println 5.daysFromNow // without parentheses
 
println "Is 2 even? " + Integer.isEven(2)
println "Is 3 even? " + Integer.isEven(3)
println new Integer(4)
println new Integer(Calendar.instance)