How to override equals when extending LinkedHashMap in groovy

Viewed 475

According to the documentation the == operator calls the equals method. This doesn't seem to be the case with maps in groovy. Is this a bug or am I doing something wrong?

When a class extends LinkedHashMap and overrides equals

class CustomExtend extends LinkedHashMap<String, String> {
    @Override
    boolean equals(Object o) {
        false
    }
}

def customExtend = new CustomExtend()
customExtend.put('key', 'value')

assert [key:'value'] == customExtend
assert customExtend == [key:'value']//should be false

Another strategy I tried is delegation

class CustomDelegate {
    @Delegate
    LinkedHashMap map = [:]
    @Override
    boolean equals(Object o) {
        false
    }
}

def customDelegate = new CustomDelegate()
customDelegate.put('key', 'value')

assert [key:'value'] == customDelegate
assert customDelegate == [key:'value']//should be false
1 Answers

Is this a bug or am I doing something wrong?

I don't think it is a bug (may be debatable), but it is behavior that might not be obvious.

Because Groovy's dynamic dispatch dispatches on runtime type, your equals(Object) isn't be invoked because Groovy provides a custom equals(Map) method for Map instances and that will win over equals(Object). One way to cause your assertion to behave the way you expect is to provide an equals(Map) method.

class CustomDelegate {
    @Delegate
    LinkedHashMap map = [:]

    boolean equals(Map o) {
        false
    }

    static void main(args) {
        def customDelegate = new CustomDelegate()
        customDelegate.put('key', 'value')

        // both of these will pass...
        assert [key: 'value'] == customDelegate
        assert customDelegate != [key: 'value']
    }
}

There are reasons you may not really want to do that, but I hope that addresses your question.

Related