https://kotlinlang.org logo
Title
r

Ray Ryan

03/23/2020, 8:42 PM
I’m probably asking this in the wrong channel, but I’m not sure what the right one is. The question is, how do you extend an abstract inner class in Kotlin? This is legal Java:
class Outer {
  abstract class Inner {
  }
}
class Child extends Outer.Inner {
  Child(Outer outer) {
    // Calls Inner constructor, providing
    // outer as the containing instance
    outer.super();
  }
}
I can’t find an equivalent in Kotlin, if I want
Child
to live in a separate file / module. The auto converter generates this, which doesn’t compile:
class Outer {
  abstract inner class Inner
}

class Child(outer: Outer?) : Inner()
🤯 2
c

Casey Brooks

03/23/2020, 8:59 PM
1) I had no idea you could do that in Java 🤯 2) I don’t think it’s possible, because constructor “super” calls are implicit, as part of the constructor declaration (not a procedural statement within the constructor body with some level of dynamic behavior to it) 3) You should structure your classes to be composed rather than inherited, which makes the relationship between
Inner
,
Outer
, and
Child
more explicit understandable. You can use the
with
scoping function within
Inner
to make it access members of
Outer
in a similar way to an inner class
For example:
class Outer {
    var outerStringProperty = ""

    open class Inner(outer: Outer, someConstructorProperty: String) {
        init {
            with(outer) {
                outerStringProperty = someConstructorProperty
            }
        }
    }
}

class Child(outer: Outer) : Outer.Inner(outer, "property")

fun createChild(): Child {
    val outer = Outer()
    return Child(outer)
}
r

Ray Ryan

03/23/2020, 9:03 PM
I understand that this is an anti pattern. I’m in a situation where my hands are tied.
Thanks though.
b

Benjamin Charais

03/24/2020, 9:00 PM
You can do this in Kotlin if you do not attach the
inner
qualifier on your kotlin inner class, this means it will not have direct access to parent methods/properties, but will compile
class Outer {
    abstract class Inner
}

class Child(outer: Outer) : Outer.Inner() {

    init {
        // Do work with outer if need be
    }
}
r

Ray Ryan

03/24/2020, 9:06 PM
Well, yes, but that’s not what I asked.
It’s a known inconsistency between the languages, and that was the question. Thanks anyway.
b

Benjamin Charais

03/24/2020, 9:24 PM
I guess I misunderstood, my fault