중첩 클래스
자바에서의 중첩 클래스
- Static을 사용하는 중첩 클래스
- 클래스 안에 static을 붙인 클래스로 밖의 클래스를 직접적으로 참조할 수 없다.
- Static을 사용하지 않는 중첩 클래스
- 내부 클래스
- 지역 클래스
- 익명 클래스
코틀린에서의 중첩 클래스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class House(
private val address: String,
private val livingRoom: LivingRoom
) {
class LivingRoom(
private var area: Double,
)
} //자바의 클래스 내부 static 클래스와 동일
class House(
private val address: String,
private val livingRoom: LivingRoom
) {
inner class LivingRoom(
private var area: Double,
) {
val address: String
get() = this@House.address
}
}
} //자바의 클래스 안의 클래스와 동일
- 기본적으로 바깥 클래스를 참조하지 않는다.
- 바깥 클래스를 참조하고 싶다면 inner 키워드를 추가한다.
- 코틀린 inner class에서 바깥 클래스를 참조하려면 this@바깥클래스를 사용해야 한다.
다양한 클래스
- Data class
- Enum class
- Sealed class, Sealed Interface
Data Class
1
2
3
4
5
6
7
8
9
public class PersonDto {
private final String name;
private final int age;
public PersonDto(String name, int age) {
this.name = name;
this.age = age;
}
}
계층 간 데이터를 전달하기 위한 DTO이다.
데이터, 생성자와 getter, equals, hashCode, toString 등이 포함되게 된다.
물론 롬복이나 record를 활용할 수도 있다.
코틀린에서는 어떻게 만들 수 있을까?
1
2
3
4
data class PersonDto(
val name: String,
val age: Int,
)
- data라는 키워드를 붙여준다.
- equals, hashCode, toString을 자동으로 만들어 준다.
- getter와 생성자는 클래스의 프로퍼티를 선언할 때 만들어진다.
- 더해 named argument까지 활용하면 builder 역할도 활용 가능하다.
Enum Class
코틀린에서는 Enum 클래스를 어떻게 구현할까?
- Enum
- 추가적인 클래스를 상속받을 수 없다.
- 인터페이스는 구현 가능하며 각 코드는 싱글톤이다.
1
2
3
4
5
6
7
enum class Country(
private val code: String,
) {
KOREA("KO"),
AMERICA("US")
;
}
- 자바와 크게 다르지 않다.
하지만 코틀린에서 Enum 클래스는 when과 함께 사용할 경우 진가를 발휘한다.
Enum + when
1
2
3
4
5
6
fun handleCountry(country: Country) {
when (country) {
Country.KOREA -> TODO()
Country.AMERICA -> TODO()
}
}
자바의 경우에는 이를 구현하기 위해 여러 if문을 사용해야 하고 else문까지 사용해야 했을 것이다.
코틀린에서는 Enum 필드에 변화가 있으면 IDE에서 경고를 주고, else 로직을 작성하지 않아도 된다.
Sealed Class, Sealed Interface
상속이 가능하도록 추상 클래스를 만들까하는데…
외부에서는 이 클래스를 상속받지 않았으면 좋겠는데 어떻게 할 수 있을까?
= 하위 클래스를 봉인하자
위와 같은 시나리오로 나타나게 된 클래스이다.
- 컴파일 타입 때 하위 클래스의 타입을 모두 기억한다.
- 즉 런타임 때 클래스 타입이 추가될 수 없다.
- 하위 클래스는 같은 패키지에 있어야 한다.
- Enum과 다른점
- 클래스를 상속받을 수 있다.
- 하위 클래스는 멀티 인스턴스가 가능하다.
1
2
3
4
5
6
7
8
sealed class HyundaiCar(
val name: String,
val price: Long
)
class Avante : HyundaiCar("아반떼", 1_000L)
class Sonata : HyundaiCar("소나타", 2_000L)
class Grandeur : HyundaiCar("그랜져", 3_000L)
- 추상화가 필요한 Entity나 DTO에 sealed Class를 활용한다.
- Enum과 같이 when과 함께 활용했을 때 효과가 크다.
1
2
3
4
5
6
7
8
9
10
11
fun main() {
handleCar(Avante())
}
private fun handleCar(car: HyundaiCar) {
when (car) {
is Avante -> TODO()
is Grandeur -> TODO()
is Sonata -> TODO()
}
}
정리
- 코틀린 inner class에서 바깥 클래스를 참조하려면 this@바깥클래스를 사용해야 한다.
- 코틀린의 Data class를 사용하면 equals, hashCode, toString을 자동으로 만들어준다.
- Enum 클래스와 비슷하지만 하위 클래스를 제한하는 Sealed Class가 존재하고 Enum과 마찬가지로 when과 함께 활용 시 효과가 뛰어나다.