4

In this post I suggested a solution that uses interface and anonymous class. However, there is one thing to be implemented: the hashCode and equals method.

However I found it is hard to implement equals for anonymous class that implements an interface. In that example the interface is Pair<L,R>, and a factory method Pairs.makePair will return an anonymous implementation for it. Suppose I added an equals implementation. The user may implement their own Pair<L,R> classes with a different equals code, therefore the call userobj.equals(makepairobj) will enter their code, and makepairobj.equals(userobj) will enter my code. Because I have no control of their code, it is hard to make sure equals to be symmetric, which is required for a good implementation.

I believe this problem is common for other cases, so I would like to know how this issue being address generally?

EDIT: In typical class, the implementation of equals will check the parameter type to make sure it is the same as its own. This guarantee only the implementing code will be called to compare the objects. However, the anonymous class do not have a name and cannot check the type with instanceof. What I can do is make sure it is an instance of the implementing interface/class. Which is not enough to prevent the above scenario.

Community
  • 1
  • 1
Earth Engine
  • 10,048
  • 5
  • 48
  • 78

3 Answers3

1

You can use this.getClass() (with either == or isAssignableFrom()) to compare the types.

Edit

As in:

public boolean equals(Object obj) {
    if (getClass() == obj.getClass()) {
        // do whatever
    }
    return false;
}
Dmitri
  • 8,999
  • 5
  • 36
  • 43
  • 4
    How does this help? You can't effectively implement the "do whatever" portion because you can't access the members of the anonymous inner class for "obj", only for "this". – David Smiley Jan 29 '14 at 17:19
  • Presumably the first step of "do whatever" is to cast to the implemented interface. An anonymous class that implements an interface, but relies on additional state (not part of the public interface) for equality would be somewhat odd. (Personally, I don't think interface + inner class is necessarily the best solution here, but that wasn't the question...) – Dmitri Jan 29 '14 at 21:33
  • If, in any case, you need to implement the interface and have some hidden state (one good example is some partial arguments), I believe we can use reflection to access that internal field, since we know everything about that field - name, type, signatue etc. – Earth Engine Nov 16 '15 at 23:45
  • I don't see how you are even going to attempt to make this work. Anonymous classes are anonymous for a reason: That first line in your code that checks equality of classes will always fail simply because of the fact that the class is anonymous. – smac89 Mar 31 '20 at 15:22
1

Usually, when you make an interface like this, it requires the implementing classes to implement equals and hashCode to follow some convention. For example, if you look at the java.util.List interface, it requires lists to be equal iff they have the same length and equal elements in the same order, and it specifies a formula for calculating the hashCode based on the hash codes of the elements.

So then "it is hard to make sure equals to be symmetric" should not be a problem.

newacct
  • 119,665
  • 29
  • 163
  • 224
1

The problem you've encountered is a sign that an anonymous class is the wrong way to implement this.

Anonymous classes are a simply a shorthand way of implementing an interface or extending a class. It's purely syntactic sugar, with no extra functionality or other advantage. They were (perhaps mistakenly) intended to make your code simpler and more readable. If an anonymous class complicates your code instead, don't use it.

Many cases that used to be a good fit for anonymous classes are now better served by lambdas. If a class has two or three methods, trying to put it in an anonymous class makes your code hard to read; it should be an inner class anyway.

erickson
  • 265,237
  • 58
  • 395
  • 493