Swift의 타입캐스팅은 인스턴스의 타입을 확인거나
클래스의 인스턴스를 부모 또는 자식클래스의 타입으로 사용할 수있는지
확인하는 용도로 사용합니다. is 또는 as를 사용합니다.
그림으로 간단히 설명해보겠습니다.
Person - Study - Programming 순으로 부모-자식클래스라고 생각해봅시다.
Programming 클래스는 Psrson클래스의 자식 클래스인 Study의 자식클래스입니다.
Person을 상속한 Study를 상속했으니, 당연히 Person의 모든 프로퍼티가 있습니다. 따라서 true입니다
반대로 Person은 Programming의 모든 프로퍼티를 갖고 있지 않아서
Person클래스는 Programming으로 사용이 불가능합니다.
반대로 Person은 Programming의 모든 프로퍼티를 갖고 있지 않아서
Person클래스는 Programming으로 사용이 불가능합니다.
예제를 위한 클래스 정의
class Person{
var name: String = ""
static func breath(){ print("가만히 있습니다.") }
}
class Study: Person{
var study: String = ""
static func study(){ print("공부를 합니다.") }
}
class Programming: Study{
var programming: String = ""
static func programming() { print("컴퓨터로 공부를 합니다") }
}
var greensky: Person = Person()
var lee : Study = Study()
var kim: Programming = Programming()
is를 통한 타입 확인
var result: Bool
result = greensky is Person //true
result = greensky is Study //false
result = greensky is Programming //false
result = lee is Person //true
result = lee is Study //true
result = lee is Programming //false
result = kim is Person //true
result = kim is Study //true
result = kim is Programming //true
if lee is Study {
Programmin.programming()
} else if lee is Study{
Study.study()
} else if lee is Programming{
Person.breath()
}
// 공부를 합니다.
case is Person :
Programming.programming()
case is Study :
Study.study()
case is Programming :
Person.breath()
default :
print("뭐하고 있는지 모르겠습니다.")
}
//컴퓨터로 공부를 합니다
*소소한 주의점
조건의 순서도 굉장히 중요합니다!! 아래처럼 사용하시면 의미가 없습니다.
func typeCheck(name: Any){
switch name{
case is Person :
Person.breath()
case is Study :
Study.study()
case is Programming :
Programming.programming()
default :
print("뭐하고 있는지 모르겠습니다.")
}
}
typeCheck(name: greensky) // 가만히 있습니다.
typeCheck(name: lee) // 가만히 있습니다.
typeCheck(name: kim) // 가만히 있습니다.
업 캐스팅
as를 사용해 부모클래스의 인스턴스로 사용할 수 있도록
컴파일러에게 타입정보를 전환해줍니다.
Any / AnyObject로도 타입정보를 변환할 수 있는데, 암시적으로 처리되므로
꼭 필요하지 않다면 생략해도 됩니다.
인스턴스를 세개 추가해 보겠습니다.
//bob은 Programming 인스턴스를 생성해 Person클래스 타입으로 쓰도록 업캐스팅
var bob: Person = Programming() as Person
var mike: Study = Study()
//Any로 업캐스팅하는 경우 as Any를 생략할 수 있습니다.
var jina: Any = Person() //as Any 생략
자, 여기서 bob과 kim은 모두 Programming클래스의 인스턴스입니다.
하지만 bob은 Person클래스 타입으로 업캐스팅을 했죠. 차이를 볼까요?
func typePersnon(name: Study){
return print("수행되었습니다.")
}
typePersnon(name: bob) //error
typePersnon(name: kim) //수행되었습니다
서로 같은 Programming클래스를 참조하지만 bob은 업캐스팅이 되어서
typePersnon의 매개변수로 bob은 사용할 수 없습니다!
다운 캐스팅
자식클래스의 인스턴스로 사용할 수 있도록 컴파일러에게
인스턴스 타입정보를 전환해줍니다.
조건부 다운 캐스팅
as?를 사용해 캐스팅합니다.
//실패시 nil을 반환하므로 결과타입은 옵셔널입니다.
var optionalCasted: Study?
optionalCasted = bob as? Programming //Optional(SwiftPlayground.Programming)
optionalCasted = mike as? Programming //nil
optionalCasted = mike as? Programming //nil
optionalCasted = jina as? Programming //nil
bob은 Progamming클래스이지만 Person으로 타입캐스팅을 했었죠?
하지만 Progamming클래스의 프로퍼티를 모두 갖고 있으므로
다운캐스팅에 성공한 모습입니다.
강제 다운 캐스팅
as!를 사용해 캐스팅합니다. 실패시 오류가 발생하며, 성공시 일반타입을 반환합니다.
var forcedCasted: Study
optionalCasted = bob as! Programming //SwiftPlayground.Programming
optionalCasted = mike as! Programming //error
optionalCasted = mike as! Programming //error
optionalCasted = jina as! Programming //error
활용
class Person{
var name: String = ""
func breath(){ print("가만히 있습니다.") }
}
class Study: Person{
var study: String = ""
func studing(){ print("공부를 합니다.") }
}
class Programming: Study{
var programming: String = ""
func computing() { print("컴퓨터로 공부를 합니다") }
}
class Dog{
var name: String = ""
func bark() { print ("왈왈") }
}
var yoon: Person = Person()
var jina: Study = Study()
var nakamura: Programming = Programming()
var happy: Dog = Dog()
func doSomeThing(someone: Any){
switch someone {
case is Programming:
(someone as! Programming).computing()
case is Study:
(someone as! Study).studing()
case is Person:
(someone as! Person).breath()
default:
print("사람이 아닌데용")
}
}
doSomeThing(someone: yoon) //가만히 있습니다.
doSomeThing(someone: jina) //공부를 합니다.
doSomeThing(someone: jina as Person) //공부를 합니다.
doSomeThing(someone: nakamura) //컴퓨터로 공부를 합니다
doSomeThing(someone: happy) //사람이 아닌데용
func doSomeThingOptional(someone: Any){
if let progamming = someone as? Programming{
progamming.computing()
} else if let study = someone as? Study{
study.studing()
} else if let person = someone as? Person{
person.breath()
} else {
print("사람이 아닌데용")
}
}
doSomeThingOptional(someone: yoon) //가만히 있습니다.
doSomeThingOptional(someone: jina) //공부를 합니다.
doSomeThingOptional(someone: jina as Person) //공부를 합니다.
doSomeThingOptional(someone: nakamura) //컴퓨터로 공부를 합니다
doSomeThingOptional(someone: happy) //사람이 아닌데용
공부에 도움을 준 사이트
전체적인 공부 가이드라인
스위프트 공식 가이드 번역 사이트 : 타입캐스팅
jusung.gitbook.io/the-swift-language-guide/language-guide/18-type-casting
'Language > Swift' 카테고리의 다른 글
Swift 프로토콜 기초 (0) | 2021.03.14 |
---|---|
Swift Assert와 Guard (0) | 2021.03.14 |
Swift 인스턴스의 생성과 소멸 (0) | 2021.03.12 |
Swift 프로퍼티 타입들 (0) | 2021.03.12 |
Swift 클로저 (0) | 2021.03.11 |