Reputation: 29510
I use a library where an abstract class overrides a concrete method inherited from Object
with an abstract method:
public abstract class A {
@Override
public abstract boolean equals(Object obj);
}
To extend this class, I have to implement the equals
method:
public class B extends A {
@Override
public boolean equals(Object obj) {
return obj != null && obj.getClass() == B.class;
}
}
Why can an abstract method (A::equals
) override a concrete method (Object::equals
)? I don't see the goal of this.
Upvotes: 19
Views: 2740
Reputation: 16024
Because all classes in Java inherently extend the Object class. Class A
will inherit the Object#equals
method. Suppose you wanted to force a compile error when the equals method is not explicitly implemented like in this example. Making the equals method abstract without an implementation block would enable you to do this.
Upvotes: 1
Reputation: 393771
In this specific example it makes perfect sense. If sub-classes of A are meant to be used in Collections, where equals
is widely used to locate objects, making A
's equals
method abstract forces you to give non-default implementation of equals
in any sub-classes of A
(instead of using the default implementation of the Object class which only compares instance references).
Of course, your suggested implementation of equals
in B makes little sense. You should be comparing the properties of the 2 B instances to determine if they are equal.
This is a more suitable implementation :
public class B extends A {
@Override
public boolean equals(Object obj) {
if (!(obj instanceof B))
return false;
B other = (B) obj;
return this.someProperty.equals(other.someProperty) && this.secondProperty.equals(other.secondProperty);
}
}
In addition, remember to override hashCode
whenever you override equals
(since the contract of equals
and hashCode
requires that if a.equals(b) == true
then a.hashCode() == b.hashCode()
).
Upvotes: 24
Reputation: 10288
This would allow you to force a subclass to reimplement a method. Whether this is a good idea or not is another matter. You would only do this if you wanted to enforce a stronger contract than the original method provided. You should then carefully document the new contract.
Upvotes: 6
Reputation: 52185
Because in this case, you would want your objects to define their own equals
, which supposedly will behave differently from the default implementation.
You should not look at this as removing functionality, but rather as enforcing that inheriting objects implement their own.
Upvotes: 10