Type Casting
코딩 강의를 보면서 is 또는 as가 언제 쓰이게 되고 왜 이렇게 쓰이는지 궁금해서 정리하게 되었습니다.
- Type Casting?
- 스위프트는 다른 프로그래밍 언어에서 대부분 지우언하는 암시적 데이터 타입 변환은 지원하지 않습니다.
- 아래의 예시는 Int(value)라는 형태의 데이터 타입으로 형태를 변경해주는데, 이는 이니셜라이저와 같습니다.
- 즉, 기존의 데이터를 전달인자로 받아 새로운 Int 구조체의 인스턴스를 생성하게 됩니다.
- 스위프트에서는 이를 타입 캐스팅이 아니라, 이니셜라이즈를 통해 새로운 인스턴스를 생성하는 과정이라합니다.
var value: Double = 3.3
var convertedValue: Int = Int(value)
convertedValue = 5.5 // error!
- 스위프트의 타입캐스팅
- 스위프트에서의 타입캐스팅은 인스턴스의 타입을 확인하거나 자신을 다른 타입의 인스턴스처럼 사용할 수 있는 방법입니다.
- 스위프트의 타입 캐스팅은 두가지가 있습니다.
- 타입을 확인하는 is
- 자식 클래스로 변환하는 다운캐스팅 as
///Coffee 클래스와 Coffee클래스를 상속받은 Latte와 Americano 클래스
class Coffee{
let name: String
let shot: Int
var description: String{
return "\(shot) shot(s) \(name)"
}
init(shot: Int) {
self.shot = shot
self.name = "coffee"
}
}
class Latte: Coffee{
var flavor: String
override var description: String{
return "\(shot) shot(s) \(flavor) latte"
}
init(flavor: String, shot: Int) {
self.flavor = flavor
super.init(shot: shot)
}
}
class Americcano: Coffee{
let iced: Bool
override var description: String{
return "\(shot) shot(s) \(iced ? "iced" : "hot") americano"
}
init(shot: Int, iced: Bool) {
self.iced = iced
super.init(shot: shot)
}
}
- 위에 선언된 클래스를 활용해서 인스턴스를 만들고 is를 사용해 확인해 보겠습니다
is. 타입 확인
let coffee: Coffee = Coffee(shot: 1)
print(coffee.description) // 1 shot(s) coffee
let myCoffee: Americcano = Americcano(shot: 2, iced: false)
print(myCoffee.description) // 2 shot(s) hot americano
let yourCoffee: Latte = Latte(flavor: "green tea", shot: 3)
print(yourCoffee.description) // 3 shot(s) green tea latte
print(coffee is Coffee) // true
print(coffee is Americcano) // false
print(coffee is Latte) // false
print(myCoffee is Coffee) // true
print(yourCoffee is Coffee) // true
print(myCoffee is Latte) // false
print(yourCoffee is Latte) // true
- 위의 결과처럼 최상위 클래스(Coffee)는 자식클래스의 Americcano, Latte를 is 로 대입한결과 false로 출력되는 것을 확인할수있지만
- Americcano, Latte는 is로 Coffee를 대입하면 true가 출력되는 것을 확인할수 있습니다.
- 부모는 자식 타입 x, 자식은 부모타입 o
as. 다운캐스팅
let actingConstant: Coffee = Latte(flavor: "vanilla", shot: 2)
print(actingConstant.description) // 2 shot(s) vanilla latte
- 위와 같은 자식클래스가 부모클래스로 변수선언이 되었을 경우 아무 문제없이 인스턴스가 생성되기 때문에, Class Latte타입의 인스턴스를 참조해야 할 경우 문제가 생길수 있습니다.
- 따라서 이런경우 actingConstant 의 타입을 Latte로 변경해 주어야 하는데 이럴경우 사용되는 키워드가 as입니다
- 하지만 다운캐스팅은 위와같은 예시처럼 false가 출력될수 있기 때문에 기본적인 리턴값이 옵셔널입니다.
- 따라서 if나 guard를 사용해서 사용해 주어야합니다.
- 그러나 확신할수 있는경우 as!를 사용할수도 있습니다.
타입캐스팅은 실제로 인스턴스를 수정하거나 값을 변경하는 작업이 아닙니다. 인스턴스는 메모리에는 똑같이 남아있을 뿐입니다.다만 인스턴스를 사용할 때 어떤 타입으로 다루고 어떤 타입으로 접근해야 할지 판단할 수 있도록 컴퓨터에 힌트를 주는 것입니다.
Any, AnyObject 타입캐스팅
- Any는 함수타입을 포함한 모든타입을 뜻하고, AnyObject는 클래스 타입만을 뜻합니다.
- 반환되는 타입이 Any 또는 AnyObject인 경우 전달받는 데이터가 어떤 타입인지 확인하고 사용해야 합니다.
스위프트는 암시적 타입 변환을 허용하지 않기 때문입니다. - 아래의 코드는 item이 어떤 타입인지 판단하며 해당 타입의 인스턴스로 사용할수 있도록 하는 코드입니다.
- Any의 경우 들어오는 타입의 케이스에 맞추어 스위치 구문으로 is나 as를 활용하여 사용할수 있습니다.
func castTypeToAppropriate(item: AnyObject){
if let castedItem: Latte = item as? Latte{
print(castedItem.description)
}else if let castedItem: Americcano = item as? Americcano{
print(castedItem.description)
}else if let castedItem: Coffee = item as? Coffee{
print(castedItem.description)
}else{
print("Inknown Type")
}
}
castTypeToAppropriate(item: coffee) // 1 shot(s) coffee
castTypeToAppropriate(item: myCoffee) // 2 shot(s) hot americano
castTypeToAppropriate(item: yourCoffee) // 3 shot(s) green tea latte
castTypeToAppropriate(item: actingConstant) // 2 shot(s) vanilla latte
팁.
옵셔널과 Any
Any타입은 모든 값 타입을 표현합니다. 더불어 옵셔널 타입도 표현할 수 있습니다. 그런데도 Any타입의 값이 들어와야 할 자리에 옵셔널 타입의 값이 위치한다면 스위프트 컴파일러는 경고를 합니다.
의도적으로 옵셔널 값을 Any타입의 값으로 사용하고자 한다면 as 연산자를 사용하여 명시적 타입 캐스팅을 해주면 경고메시지를 받지 않습니다.
let optionalValue: Int? = 100 print(optionalValue) // warning print(optionalValue as Any) // 경고 없음
자료출처
https://velog.io/@wimes/%ED%83%80%EC%9E%85%EC%BA%90%EC%8A%A4%ED%8C%85
참고페이지
jusung.gitbook.io/the-swift-language-guide/language-guide/18-type-casting
'IOS > Swift' 카테고리의 다른 글
Codable & Encodable (0) | 2020.10.21 |
---|---|
[TIL] Swift. Closure (0) | 2020.10.19 |
[TIL] Swift. GCD (Grand Central Patch) (0) | 2020.10.17 |
[TIL] Swift. Frame and Bounds (0) | 2020.10.15 |
[TIL] Swift. awakeFromNib (0) | 2020.10.14 |