본문 바로가기
개발 공부 기록하기/- Kotlin & Java

[Kotlin] 중첩클래스(Nested Class)와 내부클래스(Inner Class) 차이점

by soulduse 2023. 8. 1.
반응형

  최근에 Spring을 사용하면서 한 가지 문제에 부딪혔습니다. 특정 클래스를 내부 클래스(inner class)로 정의했더니 예상치 못한 에러가 발생했습니다. 그래서 이에 대해 조사하면서 inner class와 일반 class의 차이점을 알게 되었습니다. 이러한 경험을 토대로 이번 포스트에서는 Kotlin에서 inner class와 일반 class의 차이점에 대해 설명하고, 언제 어떤 것을 사용하는 것이 좋은지 살펴보도록 하겠습니다.

 

1. Outer 클래스에 대한 참조

inner class는 outer class에 대한 참조를 가지며, 이를 통해 outer class의 멤버에 직접 접근이 가능합니다. 이를 이해하는데 있어 아래와 같은 예시를 생각해보면 도움이 될 것입니다.

class Outer {
    private val outerVal = "Outer class"

    inner class Inner {
        fun accessOuter() {
            println("Accessing outer class from inner class: $outerVal")
        }
    }
}

fun main() {
    val myOuter = Outer()
    val myInner = myOuter.Inner()
    myInner.accessOuter() // 이 메소드를 실행하면 "Accessing outer class from inner class: Outer class"가 출력됩니다.
}

위의 예제에서 Outer 클래스에는 outerVal 이라는 private 멤버 변수가 있습니다. 그리고 Inner 클래스에서는 accessOuter 함수를 통해 outerVal에 접근하고 있습니다. 이처럼 inner class는 outer class의 private 멤버까지도 접근이 가능합니다.

이와 같은 접근이 가능한 이유는 inner class가 outer class에 대한 참조를 가지고 있기 때문입니다. 이러한 참조는 inner class가 생성될 때 outer class의 인스턴스를 사용해서 생성되기 때문에 가능해집니다. 즉, myOuter.Inner()와 같이 outer class의 인스턴스를 통해 inner class의 인스턴스를 생성하면, 이 inner class의 인스턴스는 생성 시점의 outer class 인스턴스에 대한 참조를 가지게 됩니다.

이처럼 inner class와 outer class 사이에는 밀접한 관계가 있으며, inner class는 outer class의 멤버에 직접적으로 접근할 수 있습니다. 이런 특성 때문에 특정 클래스의 동작을 확장하거나, 특정 클래스에 접근이 필요한 경우에 inner class를 사용하는 것이 좋습니다.

반대로, outer class에 대한 참조가 필요하지 않고, 독립적인 동작을 수행하는 class가 필요한 경우에는 inner class 대신 일반 class를 사용하는 것이 좋습니다. 왜냐하면 inner class는 항상 outer class에 대한 참조를 유지해야 하므로 메모리 관리 측면에서 일반 class보다 더 많은 자원을 사용할 수 있기 때문입니다.

이런 차이점을 이해하고, 각 상황에 맞는 적절한 class를 선택하면 더 효과적인 코드를 작성할 수 있을 것입니다.

 

2. 생성자

inner class는 외부 클래스의 인스턴스에 종속적이므로, 기본 생성자만으로는 인스턴스를 생성할 수 없습니다. 따라서 inner class를 인스턴스화하려면 외부 클래스의 인스턴스도 필요합니다. 반면에 일반 class는 기본 생성자로 인스턴스를 생성할 수 있습니다.

이해를 돕기 위해, 아래에 inner class와 일반 class를 사용하는 코드 예제를 들어보겠습니다.

class Outer {
    private val message: String = "Hello, world!"

    inner class Inner {
        fun printMessage() {
            println(message) // 외부 클래스의 message 속성에 액세스 가능
        }
    }

    class Nested {
        fun printMessage() {
            // println(message) // 컴파일 에러: 외부 클래스의 message 속성에 액세스 불가능
        }
    }
}

fun main() {
    val outer = Outer()
    val inner = outer.Inner() // 외부 클래스의 인스턴스가 필요
    inner.printMessage()

    val nested = Outer.Nested() // 기본 생성자만으로 인스턴스 생성 가능
    nested.printMessage()
}

위의 코드에서 Outer.Inner 클래스는 inner class로서 외부 클래스 Outer의 인스턴스에 대한 참조를 가지며, 외부 클래스의 message 속성에 액세스할 수 있습니다. 반면에 Outer.Nested 클래스는 일반 class로서 외부 클래스의 message 속성에 액세스할 수 없습니다.

 

요약

1. Kotlin에서 Inner 클래스는 Outer 클래스에 대한 참조를 가지고 있어, Outer 클래스의 멤버에 직접 접근이 가능하다.
2. 그러나 이는 Inner 클래스가 Outer 클래스와 강하게 결합되어 있다는 것을 의미하며, 이로 인해 각각 독립적으로 동작해야 하는 경우에는 적합하지 않다.
3. 따라서 각 클래스가 독립적으로 동작해야 하는 경우에는 일반 class를 사용하는 것이 좋다.

반응형