일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- SQL프로그래밍
- 동적sql
- querydsl
- dfs
- 즉시로딩
- 낙관적락
- 다대일
- 이진탐색
- BOJ
- PS
- shared lock
- FetchType
- 연결리스트
- 백트래킹
- 스토어드 프로시저
- 데코레이터
- 지연로딩
- CHECK OPTION
- 연관관계
- fetch
- eager
- 다대다
- 유니크제약조건
- 일대다
- JPQL
- execute
- 비관적락
- 힙
- exclusive lock
- 스프링 폼
- Today
- Total
흰 스타렉스에서 내가 내리지
Enum Class, Data Class, Inline Class 본문
# enum class
enum class WeekDay{ MON, TUE, WED, THU, FRI, SAT, SUN }
fun WeekDay.isWorkDay() = this == WeekDay.SAT || this == WeekDay.SUN
fun main(){
println(WeekDay.MON.isWorkDay()) // false
println(WeekDay.SAT.isWorkDay()) // true
}
# when
when을 사용하면 이넘 변수를 각각의 값과 비교할 수 있다.
when 식에서 모든 이넘 상수를 다룬 경우에는 else 가지를 생략해도 된다.
enum class Direction{
NORTH, SOUTH, WEST, EAST
}
fun rotateClockWise(direction: Direction) = when (direction){
Direction.NORTH -> Direction.EAST
Direction.EAST -> Direction.SOUTH
Direction.SOUTH -> Direction.WEST
Direction.WEST -> Direction.NORTH
}
# 커스텀 멤버가 있는 이넘 정의하기
이넘에도 확장 함수나 프로퍼티를 붙일 수 있다.
enum class WeekDay{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
val lowerCaseName get() = name.lowercase()
fun isWorkDay() = this == SATURDAY || this == SUNDAY
}
fun main(){
println(WeekDay.MONDAY.isWorkDay()) // false
println(WeekDay.WEDNESDAY.lowerCaseName) // wednesday
}
이넘 클래스에 생성자가 있으면 각 이넘 상수의 정의 뒤에도 적절한 생성자 호출을 추가해야 한다.
enum class RainbowColor(val isCold: Boolean){
RED(false), ORANGE(false), YELLOW(false),
GREEN(true), BLUE(true), INDIGO(true), VIOLET(true);
val isWarm get() = !isCold
}
fun main(){
println(RainbowColor.BLUE.isCold) // true
println(RainbowColor.RED.isWarm) // true
}
모든 이넘 값에는 ordinal과 name 이라는 한 쌍의 프로퍼티가 들어있다.
ordinal은 이넘 클래스 안에 정의된 이넘 값의 순서에 따른 인덱스이고, name은 이넘 값의 이름이다.
enum class Direction{
NORTH, SOUTH, WEST, EAST
}
fun main(){
println(Direction.WEST.name) // WEST
println(Direction.WEST.ordinal) // 2
}
각 이넘 클래스는 마치 동반 객체의 멤버처럼 호출할 수 있는 암시적인 메서드들을 제공한다.
valueOf() 메서드는 이넘 값의 이름을 문자열로 넘기면 그에 해당하는 이넘 값을 돌려주거나 이름이 잘못된 경우 예외를 던진다.
enum class Direction{
NORTH, SOUTH, WEST, EAST
}
fun main(){
println(Direction.valueOf("NORTH")) // NORTH
println(Direction.valueOf("NORTH_EAST")) // java.lang.IllegalArgumentException: No enum constant Direction.NORTH_EAST
}
코틀린1.1 부터는 values()나 valueOf() 대신에 제네릭 최상위 메서드인 enumValues()와 enumValueOf()를 사용할 수도 있다.
enum class WeekDay{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
fun main(){
val weekDays = enumValues<WeekDay>()
println(weekDays[2]) // WEDNESDAY
println(enumValueOf<WeekDay>("THURSDAY")) // THURSDAY
}
#데이터 클래스
코틀린은 데이터를 저장하기 위한 목적으로 주로 쓰이는 클래스를 선언하는 유용한 기능을 제공한다.
이런 기능을 데이터 클래스(data class)라고 부르며, 이 기능을 사용하면 컴파일러가 동등성을 비교하거나 String으로 변환하는 등의 기본 연산에 대한 구현을 자동으로 생성해준다.
그리고 구조 분해 선언 (destructuring declaration)을 활용할 수도 있다.
구조 분해를 사용하면 클래스의 프로퍼티를 간단한 한 가지 언어 구성 요소를 사용해 여러 변수에 나눠 넣을 수 있다.
데이터 클래스라고 불리는 특정 유형의 클래스에 대해서는 코틀린이 클래스의 프로퍼티 목록을 기반으로 이런 메서드를 자동으로 생성해준다.
data class Person(
val firstName: String,
val familyName: String,
val age: Int)
fun main(){
val person1 = Person("John", "Doe", 25)
val person2 = Person("John", "Doe", 25)
val person3 = person1
println(person1 == person2) // true
println(person1 == person3) // true
}
data class는, 컴파일러가 주생성자에 정의된 프로퍼티의 값을 서로 비교하는 동등성 비교 연산을 자동으로 생성해주기 때문에 두 비교가 모두 true를 반환한다.
데이터 클래스는 equals()나 hashCode() 외에 toString() 메서드의 구현도 생성해준다.
data class Person(
val firstName: String,
val familyName: String,
val age: Int)
fun main(){
val person1 = Person("John", "Doe", 25)
println(person1) // Person@23fc625e -> Person(firstName=John, familyName=Doe, age=25)
}
모든 데이터 클래스는 암시적으로 copy() 함수를 제공한다.
data class Person(
val firstName: String,
val familyName: String,
val age: Int)
fun Person.show() = println("$firstName $familyName: $age")
fun main(){
val person = Person("John", "Doe", 25)
person.show() // John Doe: 25
person.copy().show() // John Doe: 25
person.copy(familyName = "Smith").show() // John Smith: 25
person.copy(age = 30, firstName = "Jane").show() // John Doe: 30
}
# 구조 분해 선언
데이터 클래스 인스턴스로부터 각각의 프로퍼티에 대응하는 지역 변수를 정의하는 간결한 구문이다.
data class Person(
val firstName: String,
val familyName: String,
val age: Int)
fun main(){
val person: Person = Person("Ben", "Shelton", 20)
val (a, b, c) = person
println("$a $b $c") // Ben Shelton 20
}
# 인라인 클래스 (값 클래스)
인라인 클래스를 정의하려면 value class 를 클래스 이름 앞에 붙여야 한다.
JVM 백엔드를 사용하는 경우에는 @JvmInline을 value class 앞에 반드시 붙여줘야 한다.
@JvmInline
value class Dollar(val amount: Int)
@JvmInline
value class Euro(val amount: Int)
인라인 클래스의 주생성자에는 불변 프로퍼티를 하나만 선언해야 한다.
런타임에 클래스 인스턴스는 별도의 래퍼 객체를 생성하지 않고 이 프로퍼티의 값으로 표현된다.
런타임에는 호출 지점을 함수 본문으로 인라인하는 인라인 함수처럼 인라인 클래스 객체를 사용하는 위치 대신 인라인 클래스에 들어있는 값이 들어간다.
인라인 클래스도 자체 함수와 프로퍼티를 포함할 수 있다.
@JvmInline
value class Dollar(val amount: Int){
fun add(d: Dollar) = Dollar(amount + d.amount)
val isDebt get() = amount < 0
}
fun main(){
println(Dollar(15).add(Dollar(20)).amount) // 35
println(Dollar(-100).isDebt) // true
}
Dollar(15)와 같은 생성자 호출은 단순히 15라는 값을 언급하는 경우와 같아야 하므로, 인라인 클래스는 런타임에 어떠한 커스텀 코드도 실행할 수 없다.
'Kotlin' 카테고리의 다른 글
마이크로서비스 구축 (0) | 2023.09.09 |
---|---|
Kotlin 컬렉션 (0) | 2023.09.08 |
backing field (1) | 2023.09.08 |
Kotlin 기초 (4) | 2023.09.05 |