티스토리 뷰
형변환(Casting)
1. 기본 자료형 간의 형변환
ex) 정수형 123 -> 문자열형 "123"
ex) 실수형 123.5 -> 정수형 123
• 자료형 간의 형변환을 모두 기억할 수는 없고 그때마다 확인하면 된다.
val NUM1_INT: Int = 10
val NUM1_STR: String = NUM1_INT.toString()
val NUM1_INT2: Int = NUM1_STR.toInt()
println(NUM1_INT + 10) // 20 출력 : NUM1_INT은 정수형
println(NUM1_STR + 10) // 1010 출력 : Int -> String 형변환 성공
println(NUM1_INT2 + 10) // 20 출력 : String -> Int 형변환 성공
val NUM2_FLOAT: Float = 10.5f
val NUM2_DOUBLE: Double = 10.5
val NUM2_STR: String = NUM2_FLOAT.toString()
val NUM2_STR2: String = NUM2_DOUBLE.toString()
val NUM2_INT: Int = NUM2_FLOAT.toInt()
val NUM2_INT2: Int = NUM2_DOUBLE.toInt()
println(NUM2_STR + 10) // 10.510 출력 : Float -> String 형변환 성공
println(NUM2_STR2 + 10) // 10.510 출력 : Double -> String 형변환 성공
println(NUM2_INT) // 10 출력 : Float -> Int 형변환 성공. 실수형 -> 정수형은 소수점 내림
println(NUM2_INT2) // 10 출력 : Double -> Int 형변환 성공. 실수형 -> 정수형은 소수점 내림
2. 클래스 간의 형변환
• 서브 클래스 -> 슈퍼 클래스 형변환 가능.
- 반대는 불가능
ex) 슈퍼 클래스 "슈퍼슈퍼" : 멤버 A , 멤버 B / 서브 클래스 "서브서브" : 멤버 A, 멤버 B, 멤버 C
- 즉, "슈퍼슈퍼" 타입의 객체는 멤버 A, 멤버 B를 가지고 있어야 한다. "서브서브" 타입의 객체는 멤버 A, 멤버 B, 멤버 C를 가지고 있어야 한다.
- "서브서브" 타입의 객체는 멤버 A, 멤버 B를 가지고 있으므로(상속을 받았기 때문) "슈퍼슈퍼" 타입도 될 수 있는 조건을 만족함. = "서브서브" -> "슈퍼슈퍼" 형변환 가능
- 반대로 "슈퍼슈퍼" 타입의 객체는 멤버 C가 없기 때문에 "서브서브" 타입을 만족하지 못함. = "슈퍼슈퍼" -> "서브서브" 형변환 불가능
open class Warrior(var name: String, var power: Int, var type: String) {
open fun attack() {
println("기본 공격")
}
}
class DefenseWarrior(name: String, power: Int) : Warrior(name, power, "골렘") {
fun defense() {
println("방어")
}
}
val warrior: Warrior = DefenseWarrior("단단한 골렘", 100)
// warrior는 DefenseWarrior로 만든 객체이지만 attack()을 가지고 있기 때문에 Warrior로 형변환 가능.
val warrior2: DefenseWarrior = Warrior("그냥 골렘", 100, "골렘")
// 오류 발생 : DefenseWarrior 타입이라면 필요한 defense()가 Warrior엔 없으니 DefenseWarrior로 형변환 불가능.
warrior.defense() // 오류 발생 : warrior는 Warrior 클래스이기 때문에, Warrior 클래스에는 defense()가 없을 수 있음.
1. as / as?
• as
- 변수A as 타입B = 변수A의 타입을 타입B로 형변환
- 실패 시 예외 발생
• as?
- 변수A as? 타입B = 변수A의 타입을 타입B로 형변환
- 실패 시 null 반환
// as
val NUM3_ANY: Any = "Hi"
val NUM3_STR: String = NUM3_ANY as String // Any는 String의 슈퍼 클래스
println(NUM3_STR + 123) // Hi123 출력 : String으로 형변환 성공
val NUM3_INT: Int = 10
//val NUM3_STR2: String = NUM3_INT as String // 예외 발생 : Int는 String의 슈퍼 클래스가 아님.
// as?
val NUM4_ANY: Any = "Hi"
val NUM4_STR: String? = NUM4_ANY as? String // Any는 String의 슈퍼 클래스
println(NUM4_STR + 123) // Hi123 출력 : String으로 형변환 성공
val NUM4_INT: Int = 10
val NUM4_STR2: String? = NUM4_INT as? String // null 반환 : Int는 String의 슈퍼 클래스가 아님.
println(NUM4_STR2) // null 출력
2. is / is?
• is
- 객체가 주어진 자료형을 준수하는 지 여부를 식별하는 연산자.
- 변수A is 타입B
- 변수A의 자료형이 타입B인가?
- 변수A가 타입B의 인스턴스인가?
- 변수A의 타입이 타입B(클래스)의 서브 클래스인가? -> 즉, 변수A의 타입에서 타입B로 형변환이 가능한가?
- is 연산자로 형변환 가능 여부가 판단되면 스마트 캐스트가 되어 명시적으로 캐스팅하지 않아도 된다.
• !is
- is와 반대 출력 -> 객체가 주어진 자료형을 준수하지 않으면 true
// is / is?
val defenseWarrior: DefenseWarrior = DefenseWarrior("단단한 골렘", 100)
println(defenseWarrior is DefenseWarrior) // true 출력 : warrior2는 DefenseWarrior 클래스의 인스턴스이다.
println(defenseWarrior is Warrior) // true 출력 : DefenseWarrior는 Warrior의 서브 클래스이다. -> 형변환이 가능하다.
open class Warrior2(var name: String, var power: Int, var type: String) {
open fun attack() {
println("기본 공격")
}
}
class DefenseWarrior2(name: String, power: Int) : Warrior2(name, power, "골렘") {
fun defense() {
println("방어")
}
}
class HardAttackWarrior2(name: String, power: Int) : Warrior2(name, power, "오크") {
fun hardAttack() {
println("강한 공격")
}
}
fun warriorSkill(myWarrior: Warrior2) {
//myWarrior.defense() // 오류 발생 : Warrior2에는 defense()가 없음.
//myWarrior.hardAttack() // 오류 발생 : Warrior2에는 hardAttack()이 없음.
if (myWarrior is DefenseWarrior2) {
myWarrior.defense() // 방어 출력 : myWarrior가 DefenseWarrior로 스마트 캐스트
} else if (myWarrior is HardAttackWarrior2) {
myWarrior.hardAttack() // 강한 공격 출력 : myWarrior가 HardAttackWarrior2로 스마트 캐스트
} else {
myWarrior.attack() // 기본 공격 출력 : myWarrior는 Warrior2 이므로 attack() 사용
}
}
val warrior2: Warrior2 = Warrior2("평범한 고블린", 100, "고블린")
val defenseWarrior2: DefenseWarrior2 = DefenseWarrior2("단단한 골렘", 100)
val hardAttackWarrior2: HardAttackWarrior2 = HardAttackWarrior2("강력한 오크", 100)
warriorSkill(warrior2) // 기본 공격 출력
warriorSkill(defenseWarrior2) // 방어 출력
warriorSkill(hardAttackWarrior2) // 강한 공격 출력
이 글은
패스트 캠퍼스 Android 앱 개발의 정석 with Kotlin 올인원 패키지 Online
강의를 듣고 공부한 내용을 바탕으로 작성되었습니다.
'📱 Android > 💻 Kotlin' 카테고리의 다른 글
[Android/Kotlin] 20. 인터페이스(Interface) (0) | 2022.10.13 |
---|---|
[Android/Kotlin] 19. Null Safety (0) | 2022.10.13 |
[Android/Kotlin] 17. 상속 (0) | 2022.10.12 |
[Android/Kotlin] 16. 접근 제한자 (0) | 2022.10.12 |
[Android/Kotlin] 15. 클래스 2편 (2) | 2022.10.12 |