Sitemap

Kotlin Series: Nested and Inner Classes

3 min readFeb 22, 2025

--

In Kotlin, nested and inner classes offer a way to logically organize your code by defining classes within other classes. While they may seem similar, there are crucial differences in their behaviour and use cases. Understanding these distinctions helps write better-structured, maintainable, and encapsulated code.

Nested Classes

A nested class is a class declared inside another class using the class keyword. By default, nested classes do not have a reference to their outer class.

Behavior

  • Static-like by default: You can instantiate a nested class without creating an instance of the outer class.
  • No access to outer class members: A nested class cannot access properties or methods of the outer class directly.

Use Cases

  • Utility classes that are conceptually related to the outer class but don’t need access to its internal state.
  • Logical grouping of related functionality inside a class.

Example

class Document {
class Metadata {
var title: String = "Untitled"
var author: String = "Unknown"
}
}

fun main() {
val metadata = Document.Metadata() // No need to instantiate Document
println("Title: ${metadata.title}, Author: ${metadata.author}")
}

In this example, Metadata is a nested class inside Document and can be used independently.

Inner Classes

An inner class is a class inside another class but declared with the inner keyword. Unlike nested classes, an inner class has a reference to its outer class and can access its members.

Behavior

  • Not static: You need an instance of the outer class to instantiate an inner class.
  • Has access to outer class members, including private ones.

Use Cases

  • Tightly coupled behavior: When the inner class operates directly on the outer class’s instance.
  • Encapsulating helper functionality: When a helper class needs to modify or read the outer class’s state.

Get Abhishek Pathak’s stories in your inbox

Join Medium for free to get updates from this writer.

Example

class User {
private var name: String = "Abhishek Pathak"

inner class Greeter {
fun greet() {
println("Hello, $name!")
}
}

fun setName(newName: String) {
name = newName
}
}

fun main() {
val user = User()
val greeter = user.Greeter()
user.setName("Alice")
greeter.greet()
}

Here, Greeter is an inner class, allowing it to interact directly with User's private members.

Real-World Android Use Cases

Nested Class Example: Data Wrappers in API Responses

Nested classes are useful for wrapping data models within an API response handler.

class ApiResponse {
class Success<T>(val data: T)
class Error(val message: String)
}

fun handleResponse(response: ApiResponse.Success<String>) {
println("Data received: ${response.data}")
}

Here, Success and Error classes logically group different API response states inside ApiResponse without needing access to any external state.

Inner Class Example: RecyclerView Adapter ViewHolder

RecyclerView adapters often use inner classes for ViewHolder, allowing them to access the outer adapter’s data.

class MyAdapter(private val itemList: List<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: String) {
itemView.findViewById<TextView>(R.id.textView).text = item
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
return MyViewHolder(view)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(itemList[position])
}

override fun getItemCount() = itemList.size
}

In this case, MyViewHolder is an inner class because it needs access to itemList from MyAdapter.

Choosing Between Nested and Inner Classes

Press enter or click to view image in full size

Summary

  • Use Nested Classes when the inner class does not need access to the outer class.
  • Use Inner Classes when the inner class must interact with the outer class.
  • Common Android Use Cases: API response models, RecyclerView adapters, custom views, utility wrappers.

By understanding and strategically using nested and inner classes, you can improve the structure, readability, and maintainability of your Kotlin-based Android applications.

--

--

Abhishek Pathak
Abhishek Pathak

Written by Abhishek Pathak

Associate Director @ UBS | 12 Years in Software Engineering | Mobile Architecture | Tech Leader, Mentor & Writer