Back-end Skill/Kotlin

[Kotlin] 스마트캐스트(smart cast) : 코틀린에서는 프로그래머 대신 컴파일러가 캐스팅한다

Sophie소피 2023. 1. 9. 22:23

[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가지 조건이 필요하다.

  1. 어떤 식이 수라면 그 값을 반환한다.
  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