【问题标题】:Groovy - How to overload '+=' operator in a Map with compile static?Groovy - 如何在带有编译静态的 Map 中重载“+=”运算符?
【发布时间】:2015-07-20 16:42:20
【问题描述】:

在 Groovy 中,我可以重载运算符 '+' plus,如下所示:

class MutableInt {
  int val

  MutableInt(int val) { this.val = val }

  MutableInt plus(int val) {                     
    return new MutableInt(this.val += val)
  }
}

上述类适用于以下测试用例:

def m1 = new MutableInt(1);
assert (m1 + 1).val == 2;

但是,如果我需要像这样将它与Map 一起使用并使用静态编译它

@groovy.transform.CompileStatic
void compileItWithStatic() {
  Map<Long, MutableInt> mutMap = [:].withDefault{ new MutableInt(0) }
  assert (mutMap[1L] += 20).val == 20;
}
compileItWithStatic()

我收到以下错误:

*Script1.groovy: 17: [Static type checking] - 
 Cannot call <K,V> java.util.Map <java.lang.Long, MutableInt>#putAt(java.lang.Long, MutableInt) with arguments [long, int]*    

如何覆盖“+=”运算符并使用静态编译它而不会出错?

编辑:

如果我在没有编译静态的情况下这样做,它可以正常工作:

def m1 = new MutableInt(1);
assert (m1 += 1).val == 2  // <----- caution: '+=' not '+' as in previous case

但是,如果它在这样的方法内部:

@groovy.transform.CompileStatic
void compileItWithStatic_2() {
  def m1 = new MutableInt(1);
  assert (m1 += 1).val == 2
}

错误将是:

Script1.groovy: -1: Access to java.lang.Object#val is forbidden @ line -1, column -1.
1 error

附注它不适用于静态编译而不是动态编译。

【问题讨论】:

    标签: groovy compiler-errors operator-overloading


    【解决方案1】:

    赋值部分抛出错误。一个简单的+ 工作:

    class MutableInt {
      int val
    
      MutableInt(int val) { this.val = val }
    
      MutableInt plus(int val) {                     
        return new MutableInt(this.val += val)
      }
    }
    
    def m1 = new MutableInt(1);
    assert (m1 + 1).val == 2;
    
    
    @groovy.transform.CompileStatic
    def compileItWithStatic() {
      Map<Long, MutableInt> mutMap = [:].withDefault{ new MutableInt(0) }
      mutMap[1L] + 20
      mutMap
    }
    
    assert compileItWithStatic()[1L].val == 20
    

    Groovy 将 mutMap[1L] += 20 解析为 mutMap.putAt(1L, 20)。这对我来说似乎是一个错误。这有效:mutMap[1L] = mutMap[1L] + 20,尽管更冗长。


    编辑:第二个错误似乎与表达式(m1 + 1) 被解析为Object 的结果有关。这应该有效:

    @groovy.transform.CompileStatic
    void compileItWithStatic_2() {
      def m1 = new MutableInt(1) + 1;
      assert m1.val == 2
    }
    

    【讨论】:

    • 我放 'void' 来演示编译静态。通过删除 '=' 它将回到相同的实现。我稍微修改了问题代码(添加断言)。
    • Hmm.. 我是否还需要重写 putAt 方法以使用 Map 支持 '+='?
    • 不,putAt 方法是在 map 对象上调用的,而不是在 MutableInt 上。我已经更新了答案以显示正在更新的地图值
    • 嗯,这只是让一切变得冗长.. ~.~ 但它并没有真正回答我如何覆盖+= 运算符。
    • 无法覆盖+= 运算符。这是一个简单的+ 运算符。
    猜你喜欢
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    相关资源
    最近更新 更多