Kotlin
[Kotlin] TypeCasting
hvoon
2022. 9. 14. 15:51
기본 자료형 클래스 간의 형변환
fun main() {
var a1:Int = 100
//var a2:Double = a1 -> error
var a2:Double = a1.toDouble()
var b1:Double = 123.12
// var b2:Int = b1
var b2:Int = b1.toInt()
var c1:String = "12234"
var c2:Int = c1.toInt()
var d1:String = "122.34"
var d2:Double = d1.toDouble()
// val d3:String = "안녕하세요"; val number4:Int = d3.toInt() -> error
}
fun main() {
// 1. 부모 클래스 참조변수에 자식 클래스의 인스턴스를 저장
// 스마트 캐스팅 발생
val super1:SuperClass4 = SubClass41() // SuperClass: 부모클래스, SubClass41:자식
// 스마트 캐스팅 발생
val inter1:Inter4 = SubClass42() // Inter4: 부모인터페이스, SubClass42: 자식클래스
// 2. 자식 인스턴스가 부모래퍼런스 변수에 저장되었다가 다시 자식래퍼런스변수로 옮겨 저장될 때,
// 강제캐스팅이 필요하다는건 자바나 코틀린이나 같음.
// 옮겨지는 인스턴스는 반드시 자식인스턴스여야하는 제약과 똑같음.
// 다만 코틀린과 자바의 명령이 달라짐.
// 자바 문법
// val sub1:SubClass41 = (SubClass41)super1
// val sub2:SubClass42 = (SubClass42)inter1
// 코틀린에서 자식인스턴스를 담고 있는 부모래퍼런스 변수값이 자식래퍼런스 변수로 이동할 때
super1 as SubClass41 // 자바의 super1 = (SubClass41)super1 명령과 같음
inter1 as SubClass42 // 자바의 inter1 = (SubClass42)inter1 명령과 같음
// 위 명령은 super1과 inter1에 있는 레퍼런스 값을 옮기려는 자식 클래스 자료형의
// '다른 변수에 형변환 과 함께 옮기는 것이 아니라' 해당 자료형으로 변경시켜버림.
// 이 명령 이후 super1 변수의 자료형은 SubClass41이 되고
// inter1 변수의 자료형은 SubClass42가 됨
// '새로운 자식 클래스 레퍼런스 변수'로 값을 옮겨 담는 것이 아니라, 저장된 참조값을 놔두고
// '현재 변수의 자료형을 변경'해 버린다는 뜻
println("변경 후 super1 : $super1")
println("변경 후 inter1 : $inter1")
// 형변환의 유효영역은 as 명령을 감싸고 있는 중괄호 안쪽임
// 자바의 경우 위 두개의 경우 형변환전에 안전한 실행을 위해 점검을 했음
// if( super1 instanceof SubClass41 ) {
// val sub1:SubClass41 = (SubClass41)super1 //형변환 명령
// }
// 코틀린에서는
// if( super1 is SubClass41 ){
// super1 as SubClass41 // 코틀린 강제 형변환 명령
// }
// 먼저 자식 인스턴스를 부모레퍼런스에 저장
val super2:SuperClass4 = SubClass41()
val inter2:Inter4 = SubClass42()
// 다시 부모레퍼런스가 저장하고 있는 자식인스턴스를 자식 레퍼런스에 옮길텐데,
// 위에서 언급한거 처럼 코틀린은 옮기지않고, 레퍼런스 변수 자체를 변경해버립니다
// 그전에 변경이 가능하지 검사
if( super2 is SubClass41 ){
super2 as SubClass41 // if문의 중괄호 밖에서도 형변환 결과를 활용할수 있습니다.
} else {
println("형변환이 불가능합니다.")
} // 검사결과가 참이면 변환, 거짓이면 변환하지 않음
if( inter2 is SubClass42 ){
// is 에 의해 열린 if 문 안에서는 as 를 쓰지 않아도
// is 연산자 값이 true라면 형변환이 가능한 상황이므로 자동으로 스마트 캐스팅 실행됨
// 현재위치 중괄호 { } 안에는 이미 inter2 는 SubClass42의 레퍼런스로 변경된 상태이며
// 그 상태로 사용이 가능
// 다만 중괄호를 벗어나면 다시 Inter4(부모인터페이스)의 레퍼런스로 되돌아감
// 중괄호가 끝나도 계속 변경 상태를 유지하려면 inter4 as SubClass42를 사용함
}
}
open class SuperClass4
interface Inter4
class SubClass41 : SuperClass4(){
fun subMethod1(){
println("SubClass21의 subMethod1입니다")
}
}
class SubClass42 : Inter4{
fun subMethod2(){
println("SubClass21의 subMethod2입니다")
}
}
