자바의 switch는 when으로 변경할 수 있다.
자바의 switch는 문(statement)이지만 코틀린의 when은 식(expression)이다.
코들린의 When을 쓰면서 좋은 점은 enum에 대한 분기를 할 때 default를 넣지 않아도 된다는 것이다.
예를들어 아래와 같은 2대 통신사의 열거형이 있다고 하면,
public enum Telecom {
SKT,
KT,
}
어떤 처리기를 만들어주는 팩토리를 구현을 할 때 아래와 같이 만든다면 switch 끝의 라인에 에러를 만난다.
interface TelecomHandler {
void handle();
}
class TelecomFactory {
public TelecomHandler create(Telecom telecom) {
switch (telecom) {
case KT:
return new SktHandler();
case SKT:
return new KtHandler();
}
}
}
에러 메시지
error: missing return statement
}
^
이것은 자바 언어차원에서 enum에 대응하는 모든 분기(branch)를 커버해서 발생할 수 있는 경우의 수가 없지만 관습적으로 만들어주는 부분이다. 그래서 아래와 같이 default 레이블과 함께 도달할 수 없는 경우에도 예외를 발생시키는 등의 (상식적으로는) 이상한 sugar syntax를 넣어주곤 했다.
class TelecomFactory {
public TelecomHandler create(Telecom telecom) {
switch (telecom) {
case KT:
return new SktHandler();
case SKT:
return new KtHandler();
default:
throw new IllegalStateException();
}
}
}
위의 자바 코드를 Kotlin의 when으로 옮기면 아래와 같다.
class TelecomFactoryKt {
fun create(telecom: Telecom): TelecomHandler {
return when (telecom) {
Telecom.KT -> SktHandler()
Telecom.SKT -> KtHandler()
}
}
}
default 부분이 없어졌다. 굳이 default와 같은 것을 넣는다면 아래와 같이 else를 쓸 수는 있다.
class TelecomFactoryKt {
fun create(telecom: Telecom): TelecomHandler {
return when (telecom) {
Telecom.KT -> SktHandler()
Telecom.SKT -> KtHandler()
else -> throw IllegalStateException()
}
}
}
하지만 해당 부분에 도달하지 않음을 IntelliJ IDEA는 알려준다.
만약 Telecom 이 nullable하다면 의미가 있기는 하다.
그렇다면?
어떻게 default를 없앨 수 있는 것일까?
IntelliJ IDEA의 바이트코드 생성기로 보면 TABLESWITCH 라는 JVM 명령어로 만들면서 default를 컴파일러가 알아서 끼워넣어줌을 알 수 있다. (L5 부분)
TABLESWITCH
1: L3
2: L4
default: L5
L5 부분을 보면 아래와 같이 되어 있다.
L5
NEW kotlin/NoWhenBranchMatchedException
DUP
INVOKESPECIAL kotlin/NoWhenBranchMatchedException.<init> ()V
ATHROW
결국 자바코드로 코틀린 코드를 옮겨보면 NoWhenBranchMatchedException 예외를 던진다고 풀이할 수 있다.
class TelecomFactoryKt {
fun create(telecom: Telecom): TelecomHandler {
return when (telecom) {
Telecom.KT -> SktHandler()
Telecom.SKT -> KtHandler()
}
}
}
는 아래의 자바코드의 형태인 셈이다.
class TelecomFactory {
public TelecomHandler create(Telecom telecom) {
switch (telecom) {
case KT:
return new SktHandler();
case SKT:
return new KtHandler();
default:
throw new NoWhenBranchMatchedException();
}
}
}
조삼모사라고 할 수도 있지만 언어레벨이란 이런 것들이 많다. Generic도 컴파일되면 타입 소거가 되지 않는가..
'Languages' 카테고리의 다른 글
TL; DR 이란? (0) | 2018.10.04 |
---|---|
[파이썬] cgi on IIS (0) | 2015.01.15 |
0.1+0.2? 부동소수점의 정밀도 문제... (0) | 2013.10.31 |