Klitos Kyriacou
08/16/2021, 2:58 PMopen class KotlinPractice(val id: Int) {
override fun equals(other: Any?) =
this === other ||
other != null &&
other::class == KotlinPractice::class &&
(other as KotlinPractice).id == id
override fun hashCode() = id
}
Is there a reason other
is not smart-cast and instead I have to cast it to KotlinPractice manually?Luke
08/16/2021, 3:06 PMthis === other || (other as? KotlinPractice)?.id == id
edrd
08/16/2021, 3:11 PM::class
. You should use is
instead:
open class KotlinPractice(val id: Int) {
override fun equals(other: Any?) =
this === other ||
other != null &&
other is KotlinPractice &&
other.id == id
override fun hashCode() = id
}
other != null
check as is KotlinPractice
is checking that it's not a nullable type either:
open class KotlinPractice(val id: Int) {
override fun equals(other: Any?) =
this === other ||
other is KotlinPractice &&
other.id == id
override fun hashCode() = id
}
Klitos Kyriacou
08/16/2021, 3:25 PMequals
to be symmetric. Unfortunately, when using is
, baseObj == derivedObj
does not imply derivedObj == baseObj
.edrd
08/16/2021, 3:42 PMequals
in derivedObj
, otherwise it's symmetric:
open class KotlinPractice(val id: Int) {
override fun equals(other: Any?) =
this === other ||
other is KotlinPractice &&
other.id == id
override fun hashCode() = id
}
class SubKotlinPractice(id: Int) : KotlinPractice(id)
fun main() {
val kotlinPractice = KotlinPractice(1)
val subKotlinPractice = SubKotlinPractice(1)
println(kotlinPractice == subKotlinPractice) // true
println(subKotlinPractice == kotlinPractice) // true
}
x is Y
means "x is of type Y or inherits Y"Vampire
08/16/2021, 4:07 PMKotlinPractice
and overwrite equals
, thereby most probably violating symmetryid
stays non-nullableKlitos Kyriacou
08/16/2021, 4:13 PMVampire
08/16/2021, 4:15 PMopen class KotlinPractice(val id: Int) {
override fun equals(other: Any?) =
this === other ||
other is KotlinPractice &&
other::class == KotlinPractice::class &&
other.id == id
override fun hashCode() = id
}
The is
also does the null-check, while then provides smart-cast for later.
This is especially useful if you have more properties to checkKlitos Kyriacou
08/16/2021, 4:26 PMedrd
08/16/2021, 4:28 PM@OptIn(ExperimentalContracts::class)
inline fun <reified T> Any?.isOfType(): Boolean {
contract {
returns(true) implies(this@isOfType is T)
}
return this != null && this::class == T::class
}
open class KotlinPractice(val id: Int) {
override fun equals(other: Any?) =
this === other ||
other.isOfType<KotlinPractice>() &&
other.id == id
override fun hashCode() = id
}