컴파일러가 타입을 확실하게 결정할 수 없어, 스마트 캐스팅을 진행하기 어려운 경우 사용!
명시적 타입 캐스팅을 위한 두 가지 변수 제공 : as, as?
fun fetchMessage(id: Int): Any =
if (id ==1) "Record found" else StringBuilder("Data not found")
// 1. as 연산자 사용
for (id in 1..2){
println("Message length: ${(fetchMessage(id) as String).length}")
}
// 2. as? 연산자 사용
for (id in 1..2){
println("Message length: ${(fetchMessage(id) as? String)?.length ?: "---"}")
}
as 연산자를 사용해서 캐스팅 -> 객체의 타입이 예상했던 것과 다를 경우 실행 시간 예외 발생
as? 연산자를 사용해서 캐스팅 -> 안전한 캐스트 연산자인 as?는 캐스팅이 실패하면 null 할당, 엘비스 연산자를 이용해서 length를 적절히 대응시킬 수 있음
- 가능한 스마트 캐스트를 사용해라
- 스마트 캐스트가 불가능한 경우에만 안전한 캐스트 연산자를 사용해라
애플리케이션이 불타거나 무너지는걸 보고 싶다면 안전하지 않은 캐스트 연산자를 사용해라 ㅋㅋㅋ 🐶
저자 분께서는 아무래도 개그욕심이 확실히 있으신 것 같다...ㅎ
메소드가 클래스 T의 객체를 받을 때, T 클래스의 자식이라면 어떤 객체든 전달 가능,
하지만 메소드가 타입 T의 제너릭 오브젝트를 받는다면 T의 파생 클래스를 전달 불가
자기 자신과 자식 객체를 허용한다. Java에서의 <? extends T>와 같다. Kotlin에서는 out 키워드를 사용해서 이를 표시한다.
코틀린 컴파일러가 공변성을 허용하여 제네릭 베이스 타입이 요구되는 곳에 제네릭 파생 타입이 허용되도록 하길 원한다면, 타입 프로젝션 필요 !!
타입 프로젝션 (사용처 가변성, use-site variance) -> 공변성 이용
: class 선언과 동시에 class 자체의 변성을 지정하는 방법 (클래스의 in/out 지정)
공변성의 반대로, 자기 자신과 부모 객체만 허용한다. Java에서의 <? super T>와 같다. Kotlin에서는 in 키워드를 사용해서 표현한다
JVM에서는 Generic 사용 시 이레이저로 인해 compile time에 타입 정보가 사라지는데, Kotlin은 구체화된 타입 파라미터 (Reified type parameter)를 통해서 문제를 해결할 수 있다!!
https://deep-dive-dev.tistory.com/39
https://umbum.dev/612
https://ricky-simpson.tistory.com/18