How do I know if two objects of inner class have the same runtime type? In the example below I expect to see the class of aa.getClass == a.Inner and ba.getClass == b.Inner, but in fact they are both Outer.Inner and equal.
class Outer{
      class Inner{}
    }
    val a = new Outer
    val b = new Outer
    val aa = new a.Inner
    val ab = new a.Inner
    val ba = new b.Inner
    val res1 = aa.getClass == ba.getClass
    val res2 = aa.isInstanceOf[ab.type ]
    scala>      |      | defined class Outer
    scala> a: Outer = Outer@550a1967
    scala> b: Outer = Outer@5f9678e1
    scala> aa: a.Inner = Outer$Inner@70a36a66
    scala> ab: a.Inner = Outer$Inner@1dd6d4b7
    scala> ba: b.Inner = Outer$Inner@2e61d218
    scala> res1: Boolean = true
    scala> res2: Boolean = false
                ... aa.getClass == a.Inner and ba.getClass == b.Inner, but in fact they are both Outer.Inner and equal
This is not true. Inner is a class member and is unique to its parent instance of Outer. This means that both a and b have their own unique version of Inner, which are incompatible types. So a.Inner is not the same type as b.Inner, and therefore an a.Inner can never be equal to a b.Inner. I cannot assign one for the other:
scala> val z: a.Inner = aa       // aa is a.Inner, so this is ok
z: a.Inner = Outer$Inner@575d06dd
scala> val z: b.Inner = aa       // aa is not b.Inner, so it fails to compile
<console>:14: error: type mismatch;
 found   : a.Inner
 required: b.Inner
       val z: b.Inner = aa
                        ^
getClass just isn't very useful here.
We can prove this with reflection:
import scala.reflect.runtime.universe._
def tpeOf[A](a: A)(implicit tt: TypeTag[A]) = tt.tpe
scala> tpeOf(aa) =:= tpeOf(ba) // different Outer parents
res24: Boolean = false
scala> tpeOf(aa) =:= tpeOf(aa) // Same instance
res25: Boolean = true
scala> tpeOf(aa) =:= tpeOf(ab) // Same Outer parent
res26: Boolean = true
On the other hand, you can use Outer#Inner to specify that you don't care which Outer your Inner type belongs to.
val x: Outer#Inner = aa
val x: Outer#Inner = ab
val x: Outer#Inner = ba
So as stated by @BenReich, you could use aa.isInstanceOf[Outer#Inner] to check if you have any of those types, and they would all return true.
ab.type means something completely different. ab.type is a singleton type that contains nothing but ab. So naturally then, aa.isInstanceOf[ab.type] must be false, because aa is not ab, regardless of whether or not they are both a.Inner.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With