Equals Signature Correct
ID |
kotlin.equals_signature_correct |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Code Smell |
Language |
Kotlin |
Tags |
CWE:581, correctness, reliability |
Description
Reports override fun equals(other: T) declarations where the parameter type is not
Any?. Such a method overloads Any.equals rather than overriding it. Collections
and other framework code still use the inherited reference-equality from Any.
Rationale
Any.equals has the signature fun equals(other: Any?): Boolean. Declaring
fun equals(other: MyType): Boolean creates a new overload, not an override. Two
distinct methods exist at runtime: the correct one (inherited, reference-equality) and
the new one (structural equality). Collections only ever call the Any? version.
// Bad — overloads, does not override
class Widget(val id: Int) {
override fun equals(other: Widget): Boolean = id == other.id
}
val set = hashSetOf(Widget(1))
set.contains(Widget(1)) // calls Any.equals — returns false
// Good — correct signature
class Widget(val id: Int) {
override fun equals(other: Any?): Boolean = other is Widget && id == other.id
override fun hashCode() = id
}
The override keyword generates a compiler warning, not an error, when the parameter
type does not match any parent method — so the mistake compiles silently.