In Java a method only overrides if it matches the same input types exactly.
class Base
{
public boolean equals(Base b)
{
System.out.println("base equals");
return false;
}
}
class Child extends Base
{
public boolean equals(Child c)
{
System.out.println("child equals");
return true;
}
}
Here, equals(Child) cannot possibly override equals(Base) because there's the possibility someone will call the function with a Base object (there's no "selective" overriding based on type).
void do_it(Base b1, Base b2)
{
b1.equals(b2); // there's no way to know at compile time if b1 and b2 are Child objects
// only safe behavior is to call Base.equals(Base)
}
This obviously is not the desired behavior for polymorphic objects, thus the only logical solution is to allow equals to be called with a common base class. It was decided long ago in Java history that there would be one common base class Object. As a consequence, all Objects are comparable to other Objects and it's the users prerogative to do runtime type checking.
You can define your own equals method which takes a specific type, just realize that it won't behave polymorphically with base classes.
class A
{
public boolean equals(Object obj)
{
if(obj instanceof A)
{
return this.equals((A)obj);
}
return false;
}
public boolean equals(A obj)
{
// ...
}
}