3.22 Concept Note - 타입캐스팅

Jay·2025년 2월 7일

Level 3 - SingleView App

목록 보기
24/24

타입캐스팅이란 인스턴스의 타입을 알아보거나 해당 타입의 수퍼클래스 혹은 서브클래스로 변환하는 작업을 의미하는데 크게 2가지 오퍼레이터를 사용한다.

  • is : 타입체크 오퍼레이터(Type Check Operator)
  • as : 타입캐스트 오퍼레이터(Type Cast Operator)

Music 이라는 클래스를 상속받는 두개의 Classic, Hiphop 클래스를 가정해보자.


class Music {
    var title: String
    init(title: String) {
        self.title = title
    }
}


class Classic: Music {
    var composer: String
    init(title: String, composer: String) {
        self.composer = composer
        super.init(title: title)
    }
}

class Hiphop: Music {
    var rapper: String
    init(title: String, rapper: String) {
        self.rapper = rapper
        super.init(title: title)
    }
}

각 인스턴스를 상수에 할당한다.

let classic = Classic(title: "Canon", composer: "Pachelbel")
let hiphop = Hiphop(title: "Lose Yourself", rapper: "Eminem")

is 키워드를 사용하면 인스턴스의 타입을 체크해 볼 수 있다.

classic 은 Music 을 상속받는 Classic 의 인스턴스이므로 Classic 타입이면서 Music 타입이므로 타입체크를 해보면 다음과 같다.

classic is Classic  // true
classic is Music    // true
classic is Hiphop   // false

이번엔 타입을 변환하는 타입캐스팅도 크게보면 수퍼클래스로 변환하는 업캐스팅과 서브클래스로 변환하는 다운캐스팅으로 나눠 볼 수 있는데 업캐스팅은 항상 성공할 수 밖에 없으므로 as 를 다음과 같이 사용하면 간단하게 변환된다.

let test = classic as Music

test 는 Music 타입이므로 composer 프로퍼티에 접근할 수 없다. 업캐스팅은 별로 효용성이 없으므로 거의 사용하지 않아서 보통 타입캐스팅이라하면 서브클래스로 변환하는 다운캐스팅을 의미한다.
다운캐스팅은 성공가능성에 따라 타입캐스트 오퍼레이터를 2가지 형식으로 사용한다.

  • as? : 성공이 불확실한 경우에 사용하면 성공시 옵셔널타입으로 변환되고 실패하면 nil 이 된다.(옵셔널 캐스팅)
  • as! : 성공을 확신하는 경우에 사용하면 성공시 해당타입으로 변환되지만 실패하면 런타임에러가 발생하므로 주의해야 한다. (강제 캐스팅)

classic 과 hiphop 을 담은 playList 배열을 만들어 보자.

let playList = [classic, hiphop]

각 엘리먼트를 접근해보면 Music 타입이므로 이때 다운캐스팅이 필요하다.

let first = playList[0] as? Classic      // Classic?
let second = playList[1] as? Classic     // nil

다음처럼 강제캐스팅을 시도할 경우 second 에서 에러가 발생한다.

let first = playList[0] as! Classic     // Classic
let second = playList[1] as! Classic    // error

그러므로 옵셔널캐스팅과 옵셔널 바인딩을 조합하여 다음처럼 사용하는 것이 안전하다.

for item in playList {
    if let classic = item as? Classic {
        print("Classic: \(classic.title), made \(classic.composer)")
    } else if let hiphop = item as? Hiphop {
        print("Hiphop: \(hiphop.title), by \(hiphop.rapper)")
    }
}


Classic: Canon, made Pachelbel
Hiphop: Lose Yourself, by Eminem
profile
Software Engineer Specialized on iOS

0개의 댓글