중첩 클래스 (Nested Class)
정의
- 하나의 클래스가 다른 클래스의 기능과 강하게 연관되어 있다는 의미를 전달하기 위해 만들어진 형식
- 클래스 안에 또 다른 클래스가 정의되는 것
사용법
- 한 클래스안에 다른 클래스를 정의하면 기본적으로는 중첩 클래스가 된다. (조금 있다가 배우겠지만 여기에 inner 키워드를 추가하면 내부 클래스가 된다.)
- “외부클래스 이름.중첩클래스 이름” 으로 참조
내부 클래스 (Inner Class)
정의
- 중첩 클래스는 형태만 내부에 존재할 뿐 실질적으로는 서로 내용을 직접 공유할 수 없는 별개의 클래스
- 내부 클래스는 외부 클래스 객체 안에서 사용되는 클래스이므로 외부 클래스 객체의 속성이나 함수를 사용할 수 있다.
사용법
- 중첩 클래스에 inner라는 키워드를 붙여서 사용
- outer 클래스와 inner 클래스에 같은 이름의 속성이나 함수가 있다면 “this@외부클래스 이름” 으로 참조
- 내부 클래스는 혼자서 객체를 만들 수는 없고 외부 클래스의 객체가 있어야만 생성과 사용이 가능한 클래스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Outer{
var text = "Outer Class"
class Nested{
fun introduce(){
println("Nested Class")
}
}
inner class Inner{
var text = "Inner Class"
fun introduceInner(){
println(text) // println(this@Inner.text) 와 같다.
}
fun introduceOuter(){
println(this@Outer.text) //외부 클래스에 있는 text와 이름이 같으므로 this@Outer로 참조
}
}
}
fun main(){
Outer.Nested().introduce()
val outer = Outer()
val innerC = outer.Inner() // 혹은 바로 Outer().Inner()로도 선언 가능
innerC.introduceInner()
innerC.introduceOuter()
outer.text = "Changed Outer text"
innerC.introduceOuter()
}
참고사항
- 내부 클래스는 기본적으로 외부 클래스를 참조하여 객체에 접근이 가능하지만 중첩 클래스는 그렇지 않다.
1
2
3
4
5
6
7
8
9
10
11
12
13
class Outer{
var text = "Outer Class"
class Nested{
fun introduce(){
println("Nested Class, ", text) // 오류: text 참조 불가능
}
}
}
fun main(){
Outer().Nested().introduce() //오류: Nested()는 Outer() 클래스의 내부 클래스가 아니므로 참조 불가
}
- 기본은 Nested Class를 사용하는 것이 좋다. (Inner classes는 정말 필요치 않으면 쓰지 않는 게 좋다)
- Outer를 참조할 필요가 없다면 굳이 inner를 명시할 필요는 없고, 불필요한 메모리 낭비를 사전에 막을 수 있다.
- Inner classes를 보호하고 싶다면 private를 명시하자.
자바의 Nested Class
- 코틀린은 클래스 안에 다른 클래스를 선언하면 기본적으로 ‘중첩 클래스’이지만, 자바는 ‘내부 클래스’가 기본
- 자바에서는 static을 선언해야 중첩 클래스가 된다.
- Inner classes를 허용하는 자바는 Outer를 참조하지 않아도 기본 inner classes이기 때문에 불필요한 메모리 낭비와 성능 이슈를 야기
- Inner classes 내부에 숨겨진 Outer class 정보를 보관하게 되고, 결국 참조를 해지하지 못하는 경우가 생기면 메모리 누수 발생 가능, 코드를 분석하더라도 이를 찾기 쉽지 않아 해결하지 못하는 경우도 발생
- 자바의 이러한 문제점 때문에 코틀리에서는 자바와 반대로 기본은 ‘중첩 클래스’, inner를 선언하면 ‘내부 클래스’가 된다.