본문 바로가기

Swift

Type Casting

728x90

Type Casting

타입 캐스팅은 인스턴스의 타입을 확인하거나, 해당 인스턴스를 슈퍼 클래스 또는 하위 클래스로 취급하는 방법입니다. Swift에서 타입 캐스팅은 "is" 또는 "as" 연산자로 구현하며, 타입 캐스팅을 사용하여 타입이 프로토콜에 적합한지 여부도 확인할 수 있습니다. 

 

is : Checking Type

표현식 is Type

타입을 체크하는 연산자로 런타임 시점에 실제 체크가 이루어집니다. 표현식이 Type과 동일거나, 서브 클래스라면 true이고 이 외의 경우에는 false입니다. 

 

🤔 서브 클래스인 경우에도 true를 반환한다고?

class Human {
    let name: String
    init(name: String) {
        self.name = name
    }
}
class Sokyte: Human { }
class Huree: Human { }
 
let people: [Human] = [
    Sokyte.init(name: "나는쏘카이트"),
    Sokyte.init(name: "너는쏘카이트"),
    Huree.init(name: "나는후리")
]

이렇게 코드를 작성하면 people에 대해서 오류가 나지 않습니다. 두 가지 인스턴스의 슈퍼클래스가 Human으로 동일하기 때문에 둘 다 Human으로 업 캐스팅된 것입니다. 그래서 타입에 민감한 Swift에서 저장할 수 있는 것입니다.

 

for human in people {
    if human is Sokyte {
        print("저는 : \(human.name)입니다.")
    } else if human is Huree {
        print("저는 : \(human.name)입니다.")
    }
}

 

이렇게 타입 캐스팅을 통해서 해당 배열 안에 있는 타입을 조건문 분기처리 할 수 있습니다.

 

>> 위의 코드를 작성하면, 아래와 같은 결과를 얻을 수 있습니다. 

 

as : Type Casting

표현식 as  (변환할)Type
표현식 as? (변환할)Type
표현식 as! (변환할)Type

표현식의 변환할 타입과 호환된다면, 변환할 타입으로 캐스팅 된 인스턴스를 리턴. 상속 관계인 업 캐스팅과 다운 캐스팅에서 사용합니다. Any와 AnyObject 타입을 사용할 경우, 상속 관계가 아니어도 예외적으로 사용할 수 있습니다. 

 

업 캐스팅 / 다운 캐스팅 

업 캐스팅 

업 캐스팅의 경우 항상 성공하며 서브 클래스 인스턴스를 슈퍼 클래스의 타입으로 참조합니다.

 

위에서 말한 예시를 바탕으로 다시 살펴보겠습니다. 

class Human {
    let name: String = "Sokyte"
}
class Sokyte: Human {
    let major: String = "디지털미디어"
}
class Huree: Human {
    let grade: Int = 4
}

이렇게 코드를 작성하고 

 

let sokyteToHuman = Sokyte.init() as Human

이렇게 코드를 추가적으로 작성한다고 생각해봅시다.

위에서 업 캐스팅을 할 때, as 키워드를 사용할 수 있다고 했었고 위의 코드는 업 캐스팅이 된 상태입니다. 즉, Sokyte 타입의 인스턴스를 생성했지만, 이를 Human으로 업 캐스팅해서 sokyteToHuman에 저장하게 되는 것입니다. 

 

이렇게 저장이 된다면, 메모리에는 어떻게 올라가는걸까요?

실제 sokyteToHuman의 타입은 업 캐스팅된 Human타입입니다. 그러나 Human 인스턴스의 멤버만 메모리에 올라가는 것이 아닙니다. 일단 먼저, Sokyte라는 인스턴스를 만들었기 때문에 Sokyte란 인스턴스가 온전히 메모리에 올라갑니다. 

 

📌 그러나, 그 이후로 업 캐스팅이 되어서 >> human의 접근 범위가 Human으로 정해지는 것입니다. 📌

>> 그러므로 접근 범위가 Human으로 한정됩니다. 

 

업 캐스팅은 항상 성공하기 때문에, as를 명시해도 되고 직접 Type Annotation을 사용해도 됩니다.

// 1. as를 사용한 업캐스팅
let human1 = Sokyte.init() as Human
 
// 2. Type Annotation을 사용한 업캐스팅
let human2: Human = Sokyte.init()

 

다운 캐스팅 

슈퍼 클래스 인스턴스를 "서브 클래스의 타입"으로 참조합니다. 앞서 살펴본 업 캐스팅된 인스턴스를 다시 원래 서브 클래스 타입으로 참조할 때 사용합니다.

업 캐스팅과 다르게 다운 캐스팅은 실패할 수 있기 때문에 as? as! 연산자를 이용합니다. 

 

다운 캐스팅을 하고 나면, 위의 예시에서 살펴본 예제에서의 Sokyte의 멤버에도 접근할 수 있습니다. 

 

as? 

런타임 시점에 타입 캐스팅을 하며, 실패할 경우 nil을 반환합니다. 

 

as!

런타임 시점에 타입 캐스팅을 하며 실패할 경우 에러가 발생합니다. 

'Swift' 카테고리의 다른 글

Initialization - 상속과 초기화  (0) 2022.04.20
Initialization - 무엇인가  (0) 2022.04.20
Hashable  (0) 2022.04.14
MVVM+RxSwift  (0) 2022.04.07
Concurrency Programming - Intro  (0) 2022.03.28