替换静态字段

时间:2011-12-14 13:59:38

标签: groovy metaprogramming

Grails提供的CountryTagLib有一个(过时的)国家/地区列表

class CountryTagLib {
    static final ISO3166_3 = [
        "scg":"Serbia and Montenegro",
        "zmb":"Zambia"
    ]
}

我想更新此地图,以塞尔维亚和黑山的每个条目取代“塞尔维亚和黑山”条目。

更新

我不能简单地update the contents of the Mapuse metaprogramming,因为ISO3166_3的内容会被复制到静态初始化程序中的其他变量

static {
    ISO3166_3.each { k, v ->
        COUNTRY_CODES_BY_NAME[v] = k
    }
}

我需要在此静态初始化程序运行之前修改ISO3166_3的代码。我认为没有任何办法可以实现这一点,所以我只留下了将整个CountryTagLib复制粘贴到自定义标记库并在其中修改ISO3166_3的难以接受的选项。我还必须更改每个<g:countrySelect>以使用我的代码。我真的不想这样做....

2 个答案:

答案 0 :(得分:2)

为什么不直接访问地图?该字段为final,这意味着您无法修改字段本身,但不能修改其内容:

你做不到:

CountryTagLib.ISO3166_3 = xxxx // this will fail (final)

但这应该有效:

CountryTagLib.ISO3166_3.remove('scg')
..etc...

答案 1 :(得分:2)

严的方法是最干净的IMO,但供将来参考;在metaClass覆盖中链回到替换方法的一种方法是将旧方法存储在某处,然后在新方法中调用它:

class CountryTagLib {
    static final ISO3166_3 = [
        "scg":"Serbia and Montenegro",
        "zmb":"Zambia"
    ]
}

// Get a handle to our old static getISO3166_3 method
def originalGetter = CountryTagLib.metaClass.getStaticMetaMethod( 'getISO3166_3', [] as Object[] )
CountryTagLib.metaClass.static.getISO3166_3 = {
    // Call the old method, and manipulate the map it returns
    originalGetter.invoke( delegate, null ).with {
      remove('scg')
      put( 'srb', 'Serbia' )
      put( 'mon', 'Montenegro' )
      it
    }
}