0

I have this code


class Dog<T: Comparable<T>>(private val name: Str, private val weight: T): Comparable<Dog<T>> {
 override fun compareTo(other: Dog<T>): Int {
  return weight.compareTo(other.weight)
 }

 override fun equals(other: Any?): Boolean {
  if (other == null || other !is Dog<*>) return false
  return name == other.name && weight == other.weight
 }
}

* means Any? but * is accepted and Any? is not. Why is that?

ntos
  • 189
  • 10
  • 1
    `*` does not strictly mean `Any?`, it means "some type, don't care what". The `Dog` class needs a generic type parameter of `Comparable`, so it can't be created with just ANY type, therefore referring to `Dog` is invalid. – Steven Frew Jan 20 '23 at 10:49
  • Also worth pointing out, is that you cannot do `other !is Dog` (on the JVM), because the `T` would be erased at compile time. You therefore have to explicitly say that you don't care about the type parameter with `*`. – marstran Jan 20 '23 at 11:01
  • Yes, I know it must be Dog>, which will be erased at compile time, but what is the secret to this * that makes it unerasable? – ntos Jan 20 '23 at 11:02
  • I think it has been already said. `Dog<*>` means we don't care about the type param, we don't check it at all, so it is not a problem it has been erased. – broot Jan 21 '23 at 09:38
  • Ah, I guess I get it now, but please confirm it. Generics are invariant and do not retain subtyping relationships, so `Dog` is not necessarily a subtype of `Dog` without variance annotations. `*`, on the other hand, is not restricted by this , except for the fact that al its functions can only take `Nothing`. – ntos Jan 22 '23 at 03:19
  • Your wording feels strange to me, "generics don't retain subtyping", etc., but generally: yes, by default generics are invariant, so checking for `Dog` checks if it's **exactly** `Any?`. `Dog` is not a subtype of `Dog` in your case. – broot Jan 22 '23 at 08:02
  • Thanks for the confirmation. As to the wording, it ís not mine but from a book I read. – ntos Jan 22 '23 at 10:27

0 Answers0