【问题标题】:replace static field替换静态字段
【发布时间】:2011-12-14 13:59:38
【问题描述】:

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> 以使用我的标签。我真的不想这样做......

【问题讨论】:

    标签: groovy metaprogramming


    【解决方案1】:

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

    你不能这样做:

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

    但这应该可行:

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

    【讨论】:

      【解决方案2】:

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

      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
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-20
        • 1970-01-01
        • 1970-01-01
        • 2021-03-03
        • 1970-01-01
        • 2016-12-04
        • 1970-01-01
        • 2022-01-02
        相关资源
        最近更新 更多