avatarGabriel Shanahan

Summary

Kotlin distinguishes between nested and inner classes using explicit keywords, with inner classes being bound to a specific instance of the outer class and carrying a reference to it.

Abstract

In Kotlin, the distinction between nested and inner classes is made clear through the use of explicit keywords. Nested classes are static and not bound to a specific instance of the outer class, while inner classes are non-static and bound to a specific instance. Inner classes carry a reference to an object of the outer class via qualified this expressions. Anonymous inner class instances are created using object expressions, which will be covered in a future lesson. Kotlin follows the same rules as Java when it comes to resolving which 'this' expression to use in situations where there are multiple candidates.

Opinions

  • The author appreciates Kotlin's explicit distinction between nested and inner classes.
  • The author provides a mnemonic to help remember the difference between nested and inner classes.
  • The author recommends using labels to qualify 'this' expressions in situations where there are multiple candidates.
  • The author notes that labels are automatically generated for classes and can be used to qualify 'this' expressions.
  • The author suggests that qualifying 'this' expressions can be useful when accessing properties from outer classes that are shadowed in inner classes.
  • The author recommends using SAM conversion for passing lambdas instead of object expressions for SAM interfaces.
  • The author provides examples and code snippets to illustrate the concepts discussed in the article.

Nested and Inner classes

Nested vs. inner classes in Kotlin and a mnemonic for distinguishing them. An explanation of labels and qualified this expressions, with a brief note on anonymous inner classes

— — — — — — — — — — — — — — —

THE CURRENT VERSION OF THIS ARTICLE IS PUBLISHED HERE.

— — — — — — — — — — — — — — —

Tags: #FYI #KOTLIN FEATURE

This article is part of the Kotlin Primer, an opinionated guide to the Kotlin language, which is indented to help facilitate Kotlin adoption inside Java-centric organizations. It was originally written as an organizational learning resource for Etnetera a.s. and I would like to express my sincere gratitude for their support.

It is recommended to read the Introduction before moving on. Check out the Table of Contents for all articles.

Kotlin uses explicit keywords to clear up the confusion between nested classes and inner classes. To recap:

  • A nested class is a static class defined inside another class. It is not bound to a specific instance of the outer class.
  • An inner class is a non-static class defined inside another class. it is bound to a specific instance of the outer class.

Inner classes are declared using the inner keyword. A nested class marked as inner can access the members of its outer class.

Inner classes carry a reference to an object of an outer class (via qualified this, which is explained bellow):

If you’re like me, you will appreciate the fact that Kotlin is explicit about the difference between nested vs. inner classes, however you’ll immediately forget which is which anyway. Here’s a (stupid) mnemonic that I use:

  • Being nested just means you’re “sitting on a nest” — you are not bound to the nest. A stork exists independently of its nest.
  • Being inner means you’re literally inside something — you are bound to it. A stomach cannot exist independently of its enclosing person.

Anonymous inner classes

Anonymous inner class instances are created using an object expression. We haven’t covered objects yet, so we’ll come back to this in a future lesson. Just as a teaser, they look like this:

On the JVM, if the object being passed is a SAM (single-abstract-method) interface, you can pass a lambda instead. We’ll talk about SAM conversion more in a future lesson.

// Java code
interface Action {
    void act();
}

Qualified this

Tags: #KOTLIN FEATURE

When using inner classes, a situation can arise where we actually have two candidate values for this. Take a look at the following:

In these situations, Kotlin obeys the same rules as Java — unless the this expression is qualified, it refers to the innermost enclosing scope. This means that, in the above example, the type of c is B.

If we want to reference the outer this, we need to qualify the this expression with a label. We actually briefly mentioned labels when discussing the difference between anonymous functions and lambdas. Labels are an identifier that can be assigned to certain constructs by prefixing the expression by the identifier, followed by a @:

These labels can then be used to qualify this expressions and also return, break and continue statements. For more on qualifying returns and break/continue, see the article linked at the end of Function Types & Literals.

Additionally, a number of labels are generated automatically, most notably for classes. We can the use these labels to qualify our this expressions:

This might come in handy when you need to access a property from outer class (or more generally, any outer scope), which is shadowed in the inner class (scope):

We’ll come back to this topic when we talk about extension functions.

Go back to Visibility Modifiers, jump to the Table of Contents, or continue to Generics — Basics.

Join me in Etnetera
Java
Kotlin
Programming
Object Oriented
Nested Classes
Recommended from ReadMedium