•
런타임에 객체의 타입을 확인하기 위해 검사를 수행할 수 있다.
•
타입 캐스트를 사용하면 객체를 다른 타입으로 변환할 수 있다.
is 및 !is 연산자
•
is 나 !is 를 통해 객체가 주어진 타입인지 여부를 식별하는 런타임 검사를 수행한다.
if (obj is String) {
print(obj.length)
}
if (obj !is String) { // Same as !(obj is String)
print("Not a String")
} else {
print(obj.length)
}
Kotlin
복사
스마트 캐스트
•
대부분 컴파일러가 자동으로 객체를 캐스트하기 때문에 명시적 캐스트 연산자를 사용할 필요가 없다.
◦
컴파일러는 불변 값에 대한 타입 검사와 명시적 캐스트를 추적하고 필요한 경우 암묵적 캐스트를 삽입한다.
fun demo(x: Any) {
if (x is String) {
print(x.length) // x is automatically cast to String
}
}
fun demo(x: Any) {
if (x !is String) return
print(x.length) // x is automatically cast to String
}
Kotlin
복사
•
제어 흐름
◦
스마트 캐스트는 if 조건식뿐만 아니라 when 표현식과 while 루프에도 적용된다.
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
Kotlin
복사
◦
스마트 캐스트를 이용해 boolean 조건을 변수로 추출하여 사용할 수 있다.
class Cat {
fun purr() {
println("Purr purr")
}
}
fun petAnimal(animal: Any) {
val isCat = animal is Cat
if (isCat) {
// The compiler can access information about
// isCat, so it knows that animal was smart-cast
// to the type Cat.
// Therefore, the purr() function can be called.
animal.purr()
}
}
fun main(){
val kitty = Cat()
petAnimal(kitty)
// Purr purr
}
Kotlin
복사
•
논리 연산자
◦
컴파일러는 && 또는 || 연산자 왼쪽에 타입 체크가 있는 경우 오른쪽에서 스마트 캐스트를 수행한다.
// x is automatically cast to String on the right-hand side of `||`
if (x !is String || x.length == 0) return
// x is automatically cast to String on the right-hand side of `&&`
if (x is String && x.length > 0) {
print(x.length) // x is automatically cast to String
}
Kotlin
복사
•
인라인 함수
◦
외부 스코프에 있는 변수를 인라인 함수에 전달하여 사용할 때 스마트 캐스트를 수행한다.
interface Processor {
fun process()
}
inline fun inlineAction(f: () -> Unit) = f()
fun nextProcessor(): Processor? = null
fun runProcessor(): Processor? {
var processor: Processor? = null
inlineAction {
// The compiler knows that processor is a local variable and inlineAction()
// is an inline function, so references to processor can't be leaked.
// Therefore, it's safe to smart-cast processor.
// If processor isn't null, processor is smart-cast
if (processor != null) {
// The compiler knows that processor isn't null, so no safe call
// is needed
processor.process()
}
processor = nextProcessor()
}
return processor
}
Kotlin
복사
•
예외 처리
◦
스마트 캐스트 정보는 catch 및 finally 블록으로도 전달됩니다.
fun testString() {
var stringInput: String? = null
// stringInput is smart-cast to String type
stringInput = ""
try {
// The compiler knows that stringInput isn't null
println(stringInput.length)
// 0
// The compiler rejects previous smart cast information for
// stringInput. Now stringInput has the String? type.
stringInput = null
// Trigger an exception
if (2 > 1) throw Exception()
stringInput = ""
} catch (exception: Exception) {
// The compiler knows stringInput can be null
// so stringInput stays nullable.
println(stringInput?.length)
// null
}
}
Kotlin
복사
•
스마트 캐스트 전제조건
스마트 캐스트는 컴파일러가 변수의 검사와 사용 사이에 변경이 없다고 보장할 때만 작동한다.
1.
val 지역 변수
a.
항상 (로컬 위임된 프로퍼티 제외)
2.
val 프로퍼티
a.
private, internal 이 선언된 동일한 모듈에서 검사가 수행되는 경우 작동
b.
open 이 선언되었거나 커스텀 게터가 있는 경우 작동하지 않음
3.
var 지역 변수
a.
변수의 값이 검사와 사용 사이에 변경되지 않아야 작동
b.
변수가 값을 변경하는 람다에 캡쳐되지 않아야 작동
c.
변수가 로컬 위임된 프로퍼티가 아니어야 작동
4.
var 프로퍼티
a.
언제든지 다른 코드에 의해 수정될 수 있기 때문에 절대 작동하지 않음
캐스트 연산자
•
as
◦
객체를 null이 불가능한 타입으로 명시적으로 캐스팅하기 위한 연산자
◦
해당 연산자를 사용하여 nullable한 타입으로 캐스팅하려면 오른쪽에 nullable한 타입을 사용
◦
캐스트가 불가능한 경우 예외 발생
val x: String = y as String
Kotlin
복사
•
as?
◦
캐스팅 시 예외를 방지하기 위해 사용하는 연산자
◦
nullable 타입이 아닌 경우에도 캐스팅 결과는 null을 허용
val x: String? = y as? String
Kotlin
복사