[Kotlin in Action] 2장
스마트캐스트: 타입 검사와 타입 캐스트를 조합
interface Expr
class Num(val value: Int): Expr
class Sum(val left: Expr, val right: Expr): Expr
Num value라는 프로퍼티만 존재하는 단순한 클래스로 Expr 인터페이스로 존재한다.
Sum Expr타입의 객체라면 어떤 것이나 Sum 연산의 인자가 될 수 있다.
따라서 Num이나 다른 Sum이 인자로 올 수 있다.
Sum 은 Expr의 왼쪽과 오른쪽 인자에 대한 참조를
left right 프로퍼티로 저장한다.
이 예제에서 left나 right은 각각의 Sum이나 Num일 수도 있다.
(1+2)+4 라는 식을 Sum(Sum( Num(1), NumA(2)), Num(4)의 구조의 객체가 생긴다.
>>> println (eval(Sum(Sum(Num(1), Num(2), Num(4))))
7
식을 평가하려면 2가지 조건이 필요하다.
- 어떤 식이 수라면 그 값을 반환한다.
- 어떤 식이 합계라면 좌항과 우항의 값을 계산한 다음에 그 두값을 합한 값을 반환한다.
fun eval (e: Expr): Int {
if(e is Num){
val n = e as Num
return n.value
}
if(e is Sum){
return eval(e.right)+ eval(e.left)
}
throw IllegalArgumentException("Unknown expression")
}
>>> println(eval(Sum(Sum(Num(1), Num(2)), Num(4)))
7
코틀린에서는 is를 이용해 변수타입을 검사한다.
is 검사는 자바의 instanceof 와 비슷하다.
하지만 자바에서 어떤 변수의 타입을 instanceof로 확인한 다음에
그 타입에 속한 멤버에 접근하기 위해서는 명시적으로 변수 타입을 캐스팅해야한다.
이런 멤버 접근을 여러 번 수행해야 한다면 변수에 따로 캐스팅한 결과를 저장한 후 사용해야한다.
코틀린에서는 프로그래머 대신 컴파일러가 캐스팅해준다.
어떤 변수가 원하는 타입인지 일단 is로 검사하고나면 굳이 변수를 원하는 타입인지 일단 is로 검사하고 나면
굳이 변수를 원하는 타입으로 캐스팅하지않아도
마치 처음부터 그 변수가 원하는 타입으로 선언된 것처럼 사용할 수 있다 .
하지만 실제로는 컴파일러가 캐스팅을 수행해준다. 이를 스마트캐스트(smart cast)라고 부른다.
eval함수에서 e의 타입이 Num인지 검사한 다음 부분에서 컴파일러라는 e의 타입을 Num으로 해석한다.
그렇기 때문에 Num의 프로퍼티인 value를 명시적 캐스팅없이 e.value로 사용할 수 있다.
Sum의 프로퍼티인 right과 left도 마찬가지로 Sum타입인지 검사한 다음부터는
e.right 와 e.left를 사용할 수 있다.
스마트캐스트는 is로 변수에 든 값의 타입을 검사한 다음에 그 값이 바뀔 수 없는 경우에만 작동하는데
클래스의 프로퍼티에 대해 스마트 캐스트를 사용한다면 그 프로퍼티는 반드시 val이여야한다.
커스텀 접근자를 사용해서도 안된다.
val이 아니거나 val이지만 커스텀 접근자를 사용하는 경우에는 해당 프로퍼티에 대한 접근이 항상
같은 값을 내놓는다고 확신할 수 없기 때문이다.
원하는 타입으로 명시적으로 타입 캐스팅하려면 as 키워드를 사용한다.
val n = e as Num
다음시간에는 eval 함수를 리팩토링해서 더 코틀린다운 코드로 만드는 방법에 대해 살펴보도록 하겠다.
'Back-end Skill > Kotlin' 카테고리의 다른 글
[Kotlin]코틀린1.8.0에서 새롭게 업데이트 된 기능 (0) | 2023.01.25 |
---|---|
kotlinBasic 이해하기 (1) | 2022.10.05 |