So this is not a real “equals” and will not be use...
# announcements
g
So this is not a real “equals” and will not be used by system. Of course, you can use it manually, but for example HashMap or other system code just ignores these methods You can do the same thing in Kotlin, but of course it’s not correct convention for equals
u
Here is actually a hint why it might not be a good idea to resolve the
==
-operator to an overload of equals. The overload (e.g.
fun Value.equals(Value): Boolean
) would not be used by any generic code. As pointed out by @gildor, most notably by classes like HashMap. So you could have two values
a: Value
and
b: Value
with
a == b
yielding
true
. At the same time something like
fun <KeyType> keysEqual(a: KeyType, b: KeyType) = (a == b)
, as might be used in a hash map implementation to compare keys, yields
false
. So even though
a == b
hashMapOf(a to 1, b to 2)
would yield a map with two distinct elements
Not even mentioning the `equals``hashCode` contract. What a trap if overloading `equals`while overriding
hashMap
would fire back at you. So in general, you should probably not overload
hashCode
or
equals
1
b
That would be an argument how extension methods are considered in the overload resolution, would it not? You can still violate the
equals
-
hashCode
contract by overriding the
equals(other: Any?): Boolean
method which would lead to the same confusion in the existing convention
g
It’s true, but it requires to do two checks in two different methods with the same result and it’s more error prone approach.
b
How is it any more error prone to violate the
equals
-
hashCode
contract through overloading vs overriding??
g
I’m talking about multiple equals functions or operator for
==
that works as
equal
in one case and doesn’t work in another
b
That same case exists with
>
,
<
, etc. with the
compareTo
operator in the existing functionality
u
Is there a generic
compareTo
?
b
There’s isn’t a
compareTo
defined on
Any
, but the same scenario can be produced through 2 definitions of
compareTo
one for a more generic parameter than the other
u
But then you cause the issues. in my opinion, JB just refused to cause the issue them selves 😉
g
compareTo not used by JVM and do not have
Any?
contract that used by other parts of Kotlin stdlib or JVM
b
operator fun Any.compareTo(other: Any?): Any
is a valid extension function that would be used by the compiler in every context it is imported into. I agree that it’s an issue caused by the developer, but I can cause that same inconsistency through the
equals
override instead of an overload haha
g
to use compareTo you should explicitly import this extension or add it as member function
b
Exactly, which is what you would do if
equals
were resolved by overloads. Again, I’m not saying that the language as it exists right now uses overloads for the
equals
convention, but rather that I haven’t seen a strong reason why
equals
should behave differently from other contentions (even if that means that all conventions use overriding instead of overloading, although my less preferred option). Remember, conventions are just syntax sugar added by Kotlin, so whether or not the JVM/Java uses it is irrelevant since the compiler transforms to a
.compareTo
or a
.equals
method call
k
Here’s a reason
Copy code
val foo: Value = ...
val bar: Value = ...
val foobar: Any = bar

println(foo == foobar)
What version of equals would you expect the compiler to pick here? The
equals(Value)
or the
equals(Any?)
Remember,
equals
has very specific rules guiding it, and deviating from that introduces inconsistency
b
I would expect it to honor the types, so
equals(Any?)
. The same issue exists with
println(foo > foobar)
.