I have an interface and I want everyone who implements this interface to implements an overrridden \"equals\" method.
Is there a way to make sure that happens?
Edit: Probably not a good idea (see comment from FarmBoy). Leaving here for posterity.
Instead of using equals(Object obj)
from the Object
class, make them compare it to an implementation of your interface.
public interface MyInterface {
public boolean equals(MyInterface mi);
}
Therefore,
public class MyImplementation implements MyInterface {
public boolean equals(MyInterface mi)
{
if(this == mi)
return true;
// for example, let's say that each implementation
// is like a snowflake...(or something)
return false;
}
}
And then:
public class Main {
public static void main(String[] args)
{
Object o = new MyImplementation();
MyImplementation mi1 = new MyImplementation();
MyImplementation mi2 = new MyImplementation();
// uses Object.equals(Object)
o.equals(mi1);
// uses MyImplementation.equals(MyInterface)
mi1.equals(mi2);
// uses Object.equals(Object)
mi2.equals(o);
}
}
No. You can add it to the interface (and thus the javadocs), but if Object.equals has the same signature, you can't have the compiler make them override it.
No. An interface is a contract guaranteeing that methods exists.
There is no mechanism for enforcing that methods should be overridden in an interface.
I've experimented with writing the required contract for equals
in the JavaDoc. But the requirement that hashCode
is consistent with equals
results in a very complex contract for hashCode
. So I gave up and created abstract base class with a final
implementation of the two methods instead.
No, you only can create an abstract class instead of an interface like this:
public abstract class MyApi {
public final boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof MyApi) {
return equals((MyApi)other);
}
return false;
}
protected abstract boolean equals(MyApi other);
}
or a more simple version:
public abstract class MyApi {
public boolean equals(Object other) {
throw new UnsupportedOperationException("equals() not overridden: " + getClass());
}
}
EDIT (gave it a try after the comment from @CodeConfident, thanks! Never assumed it would work):
You can also simply declare equals()
in an abstract class (not in an interface!) and therefore hide the Object
implementation and enforce a new implementation in any subclass:
public abstract class MyApi {
public abstract boolean equals(Object obj);
public abstract int hashCode();
}
Anyway you should always implement equals()
and hashCode()
together to fulfil the contract.
I guess there can be two reasons why such an equals method might be required
You want to ensure that all the classes in your app (or a subset of them) "will" have the equals method. Something like standards enforcement, or making sure some of the APIs you use work as they should (and they expect equals to be implemented correctly. Say you use Maps quite a lot and want to be absolutely sure that a subset of classes are definitely possible map keys) If that is the case, this is not the way to go. In this case you will not be able to do it, but even if you are, it would not be correct. You should go for code coverage tools, and better unit testing.
You dont want THE equals method, but want a similar method. In this case you can create another method with a similar name in the interface.