Search code examples
referencekotlininner-classes

Why can't I reference a nested object using `val` or `typealias` that refers to an object?


Consider the following code:

object SomeObjectA {
    object SomeObjectB {
        val a = "test"
    }
}

val X = SomeObjectA
typealias Y = SomeObjectA

SomeObjectA.SomeObjectB // works
X.SomeObjectB // error
Y.SomeObjectB // error

I can't use val or typealias, which reference the outer object, to refer to a nested object within that outer object. Why?


Solution

  • the compiler error is comes from java, and the kotlin objects convert to java classes as below:

    public final class SomeObjectA {
        private SomeObjectA() {/**/}
    
        public static final SomeObjectA INSTANCE = new SomeObjectA();
    
        public static final class SomeObjectB {
            private SomeObjectB() {/**/}
    
            public static final SomeObjectB INSTANCE = new SomeObjectB();
        }
    }
    

    SomeObjectA.SomeObjectB is compiled to java code as below:

    SomeObjectA.SomeObjectB.INSTANCE;
    

    SomeObjectA is compiled to java code as below:

    SomeObjectA.INSTANCE
    

    we know kotlin is base on java, and java don't allow access the nested classes via instance reference, if you do the compiler will reports an error:"Error: java: unexpected type required: class,package found: variable", for example:

    SomeObjectA a = SomeObjectA.INSTANCE;
    SomeObjectB b = a.SomeObjectB.INSTANCE;// error 
                 // ^--- compiler don't know where to go? package&class or variable?   
    

    the code below, kotlin compiler will transforms the java compiler error as: "Error: Kotlin: Nested object 'SomeObjectB' accessed via instance reference".

    val a = SomeObjectA;
    val b = a.SomeObjectB;
    //        ^--- Error
    

    Type aliases do not introduce new types. They are equivalent to the corresponding underlying types.

    so the two statements below are equality:

     val a = SomeObjectA;
     typealias a2 = SomeObjectA;
    

    avoiding to the use of typealias causing unnecessary compiler error, kotlin doesn't include all nested classes in typealias.