rhzs
rhzs

Reputation: 526

Groovy - How to overload '+=' operator in a Map with compile static?

In Groovy, I can overload operator '+' plus as follow:

class MutableInt {
  int val

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

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

The above class works fine for the following test cases:

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

However, if I need to use it together with Map like this and compile it with static

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

I got the following error:

*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]*    

How can I override the '+=' operator and compile it with static without error?

EDIT:

If I am doing like this without compile static it works fine:

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

However, if it was inside the method like this:

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

The error will be:

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

P.S. It won't work with static compilation not with dynamic compilation.

Upvotes: 1

Views: 797

Answers (1)

Will
Will

Reputation: 14539

The assignment part is throwing the error. A simple + works:

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 is parsing mutMap[1L] += 20 as mutMap.putAt(1L, 20). This looks like a bug to me. This works: mutMap[1L] = mutMap[1L] + 20, albeit more verbose.


Edit: the second error seems related to the result of the expression (m1 + 1) being parsed as Object. This should work:

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

Upvotes: 1

Related Questions