Point a = ...;
ColoredPoint b = ...;
a.equals(b) // false, a says b is not a 'Point'
b.equals(a) // true, b says my 'color-ness' is irrelevant, I'm a Point -- represent!
The only way to ensure that a. equals(b) and b.equals(a) is always true is to reify the equality relation into its own first-class type or method.
class Point { public static boolean operator_equals(Point a, Point b); }
It's too bad that Java and other languages do not offer first class support for operators. a == b can be shorthand for Point.operator_equals(a, b). If there is any ambiguity at all (because b is a subclass and there exists a method ColoredPoint.operator_equals()) then raise an error and force the developer to be explicit about exactly which equality operator is intended. If such a method doesn't exist then raise an error and force the developer to say exactly what is intended by equality. (Don't fall back to reference equality!).
This would eliminate a whole lot of bugs and all the confusion around equality.