Inside an inner class, how do you access the outer class instance, and how do you disambiguate `this` when names collide between inner and outer?
answer
- this@Outer reaches enclosing instance
- Label is the class name after @
- Inner shadows same-named outer member
- Bare this == this@Inner
- Nested class: this@Outer won't compile
basics
~20 sUse a labeled this: this@Outer refers to the outer object and this@Inner (or just this) to the inner one. This lets you pick the right object when both define a property or method with the same name.
solid answer
~30 sAn `inner` class can reach its enclosing instance through Kotlin's qualified-`this` syntax: `this@Outer`. Bare `this` (or `this@Inner`) is the inner instance. When the inner and outer both expose a member with the same name, the inner one shadows the outer, so you must write `[email protected]` to reach the outer's version. This qualified-`this` mechanism also works for outer labels of deeper nesting and for receivers of extension/lambda scopes. Nested (non-inner) classes have no enclosing-instance reference at all, so `this@Outer` is a compile error there. The label after `@` is the class name, not an arbitrary alias.
code
kotlin · 8 linesclass Outer {
val name = "outer"
inner class Inner {
val name = "inner"
fun both() = "${[email protected]} + ${[email protected]}"
}
}
fun main() = println(Outer().Inner().both()) // inner + outergo deeper
Knows this@Outer exists and that it reaches the enclosing object.
Correctly resolves shadowing, uses the class-name label, and knows nested classes can't use it.
Generalizes qualified-this to lambda/extension receivers and explains name-resolution precedence precisely.
Articulates how lexical scoping plus qualified-this keeps receiver resolution unambiguous and how this scales to deeply nested DSL receivers.
## Qualified `this` Inside any class, bare `this` means 'the current instance'. In an `inner` class you sometimes need the **enclosing** instance instead. Kotlin provides **qualified this**: `this@ClassName`, where the label is the simple name of the enclosing class. ```kotlin class Outer { val name = "outer" inner class Inner { val name = "inner" fun describe(): String { val a = this.name // "inner" (same as [email protected]) val b = [email protected] // "inner" val c = [email protected] // "outer" return "$a/$b/$c" } } } // Outer().Inner().describe() -> "inner/inner/outer" ``` ## Shadowing The inner declaration `name` **shadows** the outer's `name`: an unqualified reference resolves to the closest scope, the inner. To reach the outer member you **must** qualify with `this@Outer`. Shadowing is purely a name-resolution rule; both members still exist. ## Only inner classes get an enclosing instance `this@Outer` is only valid where an enclosing instance exists — i.e. inside an `inner` class (or an object/lambda within an instance method). In a plain **nested** class there is no outer instance, so `this@Outer` does not compile. ## Labels beyond classes The same `this@Label` form disambiguates receivers in nested lambdas and extension scopes (e.g. `this@apply`, `this@run`), so the concept generalizes beyond inner classes. ## Key takeaways - `this@Outer` = enclosing instance; `this`/`this@Inner` = inner instance. - Same-named members: inner shadows outer; qualify to reach outer. - Nested (non-inner) classes cannot use `this@Outer`.
- Does `this@Outer` work inside a non-inner nested class?No. A nested class has no enclosing instance, so the label is unresolved and it fails to compile.
- Can the same label syntax be used in lambdas?Yes; receivers like `this@apply` or `this@run` use the identical qualified-this mechanism for nested receiver scopes.
saying these in an interview costs you the question
- Claiming `this@Outer` works in a plain nested class
- Thinking the label can be an arbitrary alias instead of the class name
- Saying you can't reach a shadowed outer member at all
- Believing bare `this` refers to the outer instance
- Confusing qualified-this with reflection