Bỏ qua để đến nội dung

🐢 Nested & Inner Classes

🎯 Mục tiêu: Phân biệt Nested Class (Class lồng nhau tĩnh) và Inner Class (Class lồng nhau có tham chiếu), cùng cách sử dụng Anonymous Inner Class.


Một class được khai báo bên trong class khác mặc định là Nested Class. Nó tương đương với static nested class trong Java.

Đặc điểm: Nó không giữ tham chiếu đến instance của class cha. Nó không thể truy cập các member của class cha.

class Outer {
private val bar: Int = 1
class Nested {
fun foo() = 2
// fun accessBar() = bar // ❌ Lỗi: Không thấy 'bar'
}
}
fun main() {
val obj = Outer.Nested() // Tạo trực tiếp qua Outer
println(obj.foo())
}

Nếu bạn muốn class con truy cập được member của class cha, hãy thêm từ khóa inner. Nó tương đương với non-static nested class trong Java.

Đặc điểm: Nó giữ một tham chiếu ẩn đến instance của class cha.

class Outer {
private val bar: Int = 1
inner class Inner {
fun foo() = bar // ✅ OK: Truy cập được 'bar'
fun getOuterReference(): Outer = this@Outer
}
}
fun main() {
val outer = Outer()
val inner = outer.Inner() // Tạo qua instance của Outer
println(inner.foo())
}

Được dùng khi bạn cần tạo một object từ interface hoặc abstract class mà không cần đặt tên class mới (thường dùng cho listener, callback). Dùng từ khóa object.

interface Listener {
fun onClick()
}
fun connect(listener: Listener) { /*...*/ }
fun main() {
connect(object : Listener {
override fun onClick() {
println("Clicked!")
}
})
}

Bài tập 1: Nested vs Inner

class Computer {
val cpu = "Intel"
class Spec {
// Có truy cập được cpu không?
}
inner class Process {
// Có truy cập được cpu không?
}
}

Lời giải:

  • Spec là Nested -> Không truy cập được cpu (trừ khi truyền instance Computer vào).
  • Process là Inner -> Truy cập trực tiếp được cpu.

  • Phân biệt Nested (static) và Inner (non-static)
  • Dùng inner khi cần truy cập state của class cha
  • Dùng this@Outer để lấy tham chiếu class cha
  • Tạo Anonymous class với object : Interface