[swift] 타입 캐스팅

이은수, Lee EunSoo·2024년 10월 8일
0

Swift Basic

목록 보기
21/24
post-thumbnail

개요

타입 캐스팅 (Type casting) 은 인스턴스의 타입을 확인하거나 해당 인스턴스를 자체 클래스 계층 구조의 다른 곳에서 다른 상위 클래스 또는 하위 클래스로써 취급하는 방법을 말한다.

예를 들어 일련의 클래스 계층구조가 있을때 상위클래스의 형태로 변환하거나 하위클래스 형태로 변환하는 방법을 이야기한다.

스위프트에서 클래스, 구조체, 열거형을 타입으로 통칭한다는 것을 기억하는가? 이러한 타입을 변환하고 결정한다는 의미에서 타입 캐스팅이라는 용어를 사용한다.

소스코드

설명에 사용할 계층구조를 갖는 코드를 소개한다.

class MediaItem {
    var name: String
    init(name: String) {
        self.name = name
    }
}

class Movie: MediaItem {
    var director: String
    init(name: String, director: String) {
        self.director = director
        super.init(name: name)
    }
}

class Song: MediaItem {
    var artist: String
    init(name: String, artist: String) {
        self.artist = artist
        super.init(name: name)
    }
}


let library = [
    Movie(name: "Dune", director: "Denis Villeneuve"),
    Song(name: "World's Smallest Violin", artist: "AJR"),
    Movie(name: "Forrest Gump", director: "Robert Zemeckis"),
    Song(name: "Good Night Good Dream", artist: "Nerd Connection"),
    Song(name: "Lose Yourself", artist: "Eminem")
]

타입 검사 is

is 키워드를 통해서 인스턴스의 타입을 검사 할 수 있다.

for item in library{
    if item is Movie{
        print("\(item.name) is movie")
    }else{
        print("\(item.name) is song")
    }
}

Dune is movie
World's Smallest Violin is song
Forrest Gump is movie
Good Night Good Dream is song
Lose Yourself is song	

이처럼 is는 인스턴스와 is 뒤에 오는 타입과 동일한지 확인하고 동일하다면 true를 반환, 아니라면 false를 반환한다.

타입 캐스팅이란?

타입 캐스팅을 이해하려면, 타입 캐스팅이 항상 성공하는 것은 아니라는 점을 염두에 두어야 한다.

타입의 계층구조를 설명할 때 마트료시카 인형을 비유로 생각할 수 있다. 작은 인형이 큰 인형 안에 들어가서 큰 인형인 척(업 캐스팅)할 수 있지만, 반대로 큰 인형이 작은 인형인 척하는 것(다운 캐스팅)은 불가능하다.

이는 타입이 서로 호환되지 않는 경우를 의미한다.

물론 마트료시카처럼 불가능한 것은 아니며, 경우에 따라서는 큰 인형이 작은 인형과 동일한 계층구조를 가지는 경우 타입 캐스팅이 성공할 수도 있다.

업 캐스팅

앞서 설명한 것처럼 업캐스팅은 실패하지 않는다. 하위 타입의 경우 이미 상위 타입을 상속하고 있기에 상위 타입의 기능은 모두 구현하고 있기 때문이다.

업캐스팅 방법은 간단하다 as키워드를 사용하면 된다.

var contact: Movie = Movie(name: "Contact", director: "Robert Zemeckis")

var movieName = contact as MediaItem

이렇게 as키워드를 통해서 업 캐스팅이 가능하다.

물론 다운캐스팅에서 사용하는 as!, as?를 사용해도 되긴한다만 업캐스팅의 경우 반드시 성공하기때문에 사용할 필요는 없다.

다운 캐스팅 as

문제는 다운캐스팅이다 위에서 설명한것처럼 상위에서 하위타입으로 변환하는 경우 실패가능성이 존재한다.

다운캐스팅의 경우 성공하기 위해서는 다운캐스팅하려는 존재가 같은 타입의 존재 여야 캐스팅이 성공 할 수 있다.

이런 형태의 다운캐스팅의 필요성에 대해 의문을 가질 수 있다.

"같은 타입으로만 캐스팅이 가능하면 도대체 왜쓰는거야?"

필자또한 동일한 처음 다운캐스팅을 접했을 때 동일한 의문을 가졌다.

다운 캐스팅의 경우 사용하는 경우가 조금 특별한데 사용하는 경우는 1) 업캐스팅한 인스턴스를 다시 원래 타입으로 되돌리고자 할때나 선언했을때 부터 2) 상위 타입으로 생성했다가 다시 원래 타입으로 되돌리고자하는 상황에서 사용하는 기능이라고 생각하면된다.


사용방법은 업캐스팅과 마찬가지로 as키워드를 통해서 타입캐스팅을 하는데 다운캐스팅의 경우 실패 가능성이 존재하는 만큼 그냥 as는 사용이 불가능 하다.

그래서 옵셔널에서 익숙했던 형태인 ?!을 사용한 as!, as? 이렇게 두개의 키워드를 사용한다.

as?

as?는 타입캐스팅 하는 요소를 옵셔널로 반환한다.

class Animal {
    func makeSound() {
        print("Some sound")
    }
}

class Dog: Animal {
    func bark() {
        print("Woof!")
    }
}

let animal: Animal = Dog()  // 업캐스팅
if let dog = animal as? Dog {  // 다운캐스팅
    dog.bark()  // "Woof!"
}

다음은 다운캐스팅에 성공한 경우이다.

업캐스팅으로 생성한 인스턴스를 원래 타입으로 되돌리는 상황이다.


let someMovie = MediaItem(name: "Contact")
let contact2016 = someMovie as? Movie

print(contact2016)
nil

위 코드는 다운 캐스팅에 실패한 경우이다.

다운캐스팅이 성공하기 위해서는 타입계층 완전히 동일해야 한다.

as!

as!는 옵셔널에서 처럼 강제로 다운캐스팅한 데이터를 강제 언래핑한다. 런타임 오류가 발생 할 수 있기 때문에 사용에 주의 해야 한다.

as!의 경우 다운캐스팅이 안되는 구조라면 아예 컴파일 자체가 안되므로 사용에 유의하자, 왠만하면 as?를 사용할것

class Animal {
    func makeSound() {
        print("Some sound")
    }
}

class Dog: Animal {
    func bark() {
        print("Woof!")
    }
}

let animal: Animal = Dog()  // 업캐스팅
let dog = animal as! Dog  // 다운캐스팅
dog.bark()  // "Woof!"

as!는 강제 언래핑을 하기에 반환값이 옵셔널이 아니라서 as?처럼 if-let등으로 옵셔널바인딩을 할 필요는 없다.

하지만 명심해야 할점은 as!는 런타임 오류를 발생시킬 가능성을 갖고 있기때문에 다운캐스팅이 100%확실하게 될 상황일때만 사용하고

왠만하면 as?를 사용하는것을 추천한다.

정리

  1. swift의 타입을 검사하는 is키워드가 있다.
  2. 타입캐스팅은 인스턴스의 타입을 상위혹은 아래로 변환하는것을 말한다.
    1.타입캐스팅에는 업캐스팅, 다운캐스팅이 있다
  3. 업캐스팅에는 as, 다운캐스팅에는 as! as?를 사용한다.
profile
iOS 개발자 취준생, 천 리 길도 한 걸음부터

0개의 댓글