I have a class

data classOuter (
    val str: String = "fOo"
    ...
    val innerClassInstance: InnerClass= InnerClass(),
) {

  ...
  inner class InnerClass {
     fun foo () {     
         return str.toLowerCase()
     }
  }
}

But I get an error:

Constructor of inner class InnerClass can be called only with receiver of containing class

Is there way to avoid it ?

2

There are 2 best solutions below

0
Renat On BEST ANSWER

There is chicken and egg problem. Inner class object refers parent class object, which is not yet constructed at this point (at the point of passing parameters to the constructor of parent class).

You may employ lazy initialisation of nested class object, so it would be initialised at the time parent class object already exists. Like:

data class classOuter (
    val str: String = "foo"
) {
  val innerClassInstance: InnerClass by lazy { this.InnerClass() }

  inner class InnerClass {
     fun foo () : String {     
         return str.toLowerCase()
     }
  }
}

fun main() {
    println(classOuter("bar").innerClassInstance.foo())
}
0
Andrey On

As per docs Inner classes carry a reference to an object of the outer class, so you need at first initiate the Outer class. As you are trying to pass InnerClass to the constructor of the OuterClass it will cause java.lang.StackOverflowError in the end.

If you remove InnerClass out of constructor it will work:

fun main() {
    val innerClass = OuterClass().InnerClass()
    val outerClass = OuterClass()
    innerClass.foo()
    println(outerClass.name)
}

class OuterClass {

    val name: String = "Foo"

    inner class InnerClass {

        fun foo() {
            println("Nested")
            println(name)
        }
    }
}