rspec/rules/S2160/java/rule.adoc

93 lines
2.4 KiB
Plaintext

This rule raises an issue when a subclass of a class that overrides `Object.equals` introduces new fields
but does not also override the `Object.equals` method.
== Why is this an issue?
When a class overrides `Object.equals`, this indicates that the class not just considers object identity as equal
(the default implementation of `Object.equals`) but implements another logic for what is considered equal in the context of this class.
Usually (but not necessarily), the semantics of `equals` in this case is that two objects are equal when their state is equal field by field.
Because of this, adding new fields to a subclass of a class that overrides `Object.equals` but not updating the implementation of `equals`
in the subclass is most likely an error.
== How to fix it
Consider the following example:
[source,java]
----
class Foo {
final int a;
@Override
public boolean equals(Object other) {
if (other == null) return false;
if (getClass() != other.getClass()) return false;
return a == ((Foo) other).a;
}
}
----
[source,java,diff-id=1,diff-type=noncompliant]
----
class Bar extends Foo { // Noncompliant, `equals` ignores the value of `b`
final int b;
}
----
Override the `equals` method in the subclass to incorporate the new fields into the comparison:
[source,java,diff-id=1,diff-type=compliant]
----
class Bar extends Foo { // Compliant, `equals` now also considers `b`
final int b;
@Override
public boolean equals(Object other) {
if (!super.equals(other)) return false;
return b == ((Bar) other).b;
}
}
----
In case the new fields should not be part of the comparison because they are, for example,
auxiliary variables not contributing to the object value (), still override the method to make the point clear
that this was not just forgotten:
[source,java,diff-id=1,diff-type=compliant]
----
class Bar extends Foo { // Compliant, we do explicitly not want to take `b` into account
final int b;
@Override
public boolean equals(Object other) {
return super.equals(other);
}
}
----
== Resources
=== Documentation
* https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-[Object.equals - Java SE 8 API Specification]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Override the "equals" method in this class
endif::env-github,rspecator-view[]