반응형
728x90
반응형
enum
enum은 class 앞에 있을때는 특별한 의미를 지니지만, 다른 곳에서는 이름에 사용할 수 있다.
이를 소프트 키워드(soft keyword)라고 부른다.
enum class Color {
RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET;
}
이름에 사용할 수 있다?
예를들어 class는 키워드다.
class는 이름 자체로 사용할 수 없어서, class 라는 이름을 사용하려면 clazz 또는 aClass 등과 같이 사용해야한다.
enum 예제 구현해보기
enum class Color2 (
val r: Int, val g: Int, val b: Int // 상수의 프로퍼티를 정의한다.
) {
RED(255, 0, 0), ORANGE(255, 165, 0), // 각 상수를 생성할때 그에 대한 프로퍼티 값을 지정한다.
YELLOW(255, 255, 0), GREEN(0, 255, 0), BLUE(0, 0, 255),
INDIGO(75, 0, 130), VIOLET(238, 130, 238); // ; 을 여기서 꼭 사용해야한다.
// enum 클래스 안에서 함수를 정의한다.
fun rgb() = (r * 256 + g) * 256 + b
}
- 상수의 프로퍼티를 정의한다.
enum class Color2 (
val r: Int, val g: Int, val b: Int // 상수의 프로퍼티를 정의한다.
)
- 각 상수를 생성할때 그에 대한 프로퍼티 값을 지정한다.
RED(255, 0, 0), ORANGE(255, 165, 0), // 각 상수를 생성할때 그에 대한 프로퍼티 값을 지정한다.
YELLOW(255, 255, 0), GREEN(0, 255, 0), BLUE(0, 0, 255),
INDIGO(75, 0, 130), VIOLET(238, 130, 238); // ; 을 여기서 꼭 사용해야한다.
- 세미콜론(;)을 꼭 사용해야한다.
INDIGO(75, 0, 130), VIOLET(238, 130, 238); // ; 을 여기서 꼭 사용해야한다.
when
- 함수의 반환값으로 when 식을 직접 사용한다.
// 함수의 반환값으로 when 식을 직접 사용한다.
fun getMnemonic(color: Color2) =
when (color) { // 색이 특정 enum 상수와 같을때 그 상수에 대응하는 문자열을 돌려준다.
// break 문을 쓰지 않아도 된다.
RED -> "Richard"
ORANGE -> "Of"
YELLOW -> "York"
GREEN -> "Gave"
BLUE -> "Battle"
INDIGO -> "In"
VIOLET -> "Vain"
}
- 한 when 분기 안에 여러 값을 사용할 수 있다.
// 한 when 분기 안에 여러 값을 사용할 수 있다.
fun getWarmth(color: Color2) =
when (color) {
RED, ORANGE, YELLOW -> "warm"
GREEN -> "natural"
BLUE, INDIGO, VIOLET -> "cold"
}
- when 식의 인자를 아무 객체나 사용할 수 있다.
setOf 함수
- 인자로 전달받은 여러 객체를 그 객체들을 포함하는 집합인 Set 객체로 만드는 코틀린 표준 라이브러리집합
- set은 원소가 모여있는 컬렉션으로, 각 원소의 순서는 중요하지 않다.
- SetOf(c1, c2) 와 setOf(RED, YELLOW) 가 같다는 말은 c1이 RED고, c2가 YELLOW 또는 c1이 YELLOW, c2 RED인 경우다.
fun mix(c1 : Color2, c2: Color2) {
// when 식의 인자를 아무 객체나 사용할 수 있다.
// when 은 이렇게 인자로 받은 객체가 각 분기 조건에 있는 객체와 같은지 테스트한다.
when (setOf(c1, c2)) {
setOf(RED, YELLOW) -> ORANGE
setOf(YELLOW, BLUE) -> GREEN
setOf(BLUE, VIOLET) -> INDIGO
else -> throw Exception("Dirty color") // 매치되는 분기 조건이 없으면 이 문장을 실행한다.
}
}
- 인자 없는 when 을 사용할 수 있다.
- when에 아무 인자도 없으려면 각 분기의 조건이 boolean 결과를 계산하는 식이여야한다.
// 인자없는 when 사용
fun mixOptimized(c1 : Color2, c2 : Color2) =
// when에 아무 인자도 없으려면 각 분기의 조건이 boolean 결과를 계산하는 식이여야한다.
when {
(c1 == RED && c2 == YELLOW) ||
(c1 == YELLOW && c2 == RED) -> ORANGE
(c1 == YELLOW && c2 == BLUE) ||
(c1 == BLUE && c2 == YELLOW) -> GREEN
(c1 == BLUE && c2 == VIOLET) ||
(c1 == VIOLET && c2 == BLUE) -> INDIGO
else -> throw Exception("Dirty color") // 매치되는 분기 조건이 없으면 이 문장을 실행한다.
}
클래스 계층
- 식을 위한 Expr 인터페이스
- Sum, Num 클래스가 Expr 인터페이스를 구현한다.
- Expr 인터페이스는 아무 메서드도 선언하지 않으며, 단지 여러 타입의 식 객체를 아우르는 공통 타입 역할만 수행한다.
interface Expr
class Num(val value: Int) : Expr
// Expr 타입의 객체라면 어떤 것이나 Sum 연산의 인자가 될 수 있다. 따라서 Num 이나 다른 Sum이 인자로 올수있다.
class Sum(val left: Expr, val right: Expr) : Expr
스마트 캐스트
- is 를 사용하여 변수 타입을 검사한다. (=java의 instanceOf 와 비슷하다.)
- 코틀린에서는 프로그래머 대신 컴파일러가 캐스팅을 해준다.
- 어떤 변수가 원하는 타입인지 일단 is로 검사하고 나면 굳이 변수를 원하는 타입으로 캐스팅하지 않아도, 마치 처음부터 그 변수가 원하는 타입으로 선언된 것처럼 사용할 수 있다.
fun eval(e: Expr): Int {
if (e is Num) {
// e 의 타입을 컴파일러는 Num 으로 해석한다.
val n = e as Num // 여기서 Num 으로 타입을 변환하는데 이는 불필요한 중복이다.
return n.value
}
if (e is Sum) {
// e 의 타입을 컴파일러는 Sum 으로 해석한다.
return eval(e.right) + eval(e.left) // 변수 e에 대해 스마트 캐스트를 사용한다.
}
throw IllegalArgumentException("Unknown expression")
}
1) e의 타입을 컴파일러는 Num으로 해석한다.
if (e is Num) {
2) e의 타입을 컴파일러는 Sum으로 해석한다.
if (e is Sum) {
- 위 코드를 when 으로 전환해보자.
fun evalWhen(e: Expr) : Int =
when(e) {
is Num -> e.value
is Sum -> evalWhen(e.right) + evalWhen(e.left)
else -> throw IllegalArgumentException("Unknown expression")
}
- main 메서드를 선언해보자.
fun main() {
println(eval(Sum(Sum(Num(1), Num(2)), Num(4))))
}
- 위 main 메서드의 실행을 로깅해보자.
fun main() {
println(evalWithLogging(Sum(Sum(Num(1), Num(2)), Num(4))))
}
* 식이 본문인 함수 : 블록을 본문으로 가질 수 없다.
* 블록이 본문인 함수 : return 문이 반드시 존재해야한다.
fun evalWithLogging(e: Expr): Int =
when (e) {
is Num -> {
println("num: ${e.value}")
e.value // 반환값 (블록의 마지막 식이 블록의 결과 라는 규칙은 블록이 값을 만들어내야하는 경우 항상 성립)
}
is Sum -> {
val left = evalWithLogging(e.left)
val right = evalWithLogging(e.right)
println("sum $left + $right")
left + right // 반환값
}
else -> throw IllegalArgumentException("Unknown expression")
}
반응형
'Coding > Kotlin' 카테고리의 다른 글
[Kotlin in Action] 6. 예외처리 (throw, try~catch~finally) (0) | 2022.05.16 |
---|---|
[Kotlin in Action] 5. while과 for 루프, Map 이터레이션, in으로 원소검사 (0) | 2022.05.15 |
[Kotlin in Action] 3. 클래스, 프로퍼티 (0) | 2022.05.13 |
[Kotlin in Action] 2. 변수, 문자열 템플릿 (0) | 2022.05.12 |
[Kotlin in Action] 1. Hello Kotlin 기본 코드 분석하기 (0) | 2022.05.11 |