GGURUPiOS

Swift 공식 문서 정리 - (19) Type Casting 본문

Swift/공식문서 정리 ( 문법 )

Swift 공식 문서 정리 - (19) Type Casting

꾸럽 2023. 5. 14. 15:37

Type Casting(타입 캐스팅)

타입 캐스팅은 인스턴스의 타입을 확인하거나 인스턴스를 같은 계층에 있는 다른 슈퍼클래스나 서브클래스로 취급하는 방법임

타입캐스팅에는 is, as 두 연산자를 사용

타입 캐스팅을 위한 클래스 계층구조 선언

예제클래스

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: "Casablanca", director: "Michael Curtiz"),
    Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
    Movie(name: "Citizen Kane", director: "Orson Welles"),
    Song(name: "The One And Only", artist: "Chesney Hawkes"),
    Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
]

library가 갖고있는 Movie, Song 인스턴스의 공통 부모는 MediaItem 이기때문에

library는 타입추론에 의해 [MediaItem] 배열의 형을 갖게 됨

library를 순회하면 배열의 아이템은 Movie, Song 타입이 아니라 MediaItem 타입임

타입지정을 위해서는 downcasting 을 이용해야 함

타입 확인

is 연산자를 이용해 특정 인스턴스의 타입을 확인할 수 있음

var movieCount = 0
var songCount = 0

for item in library {
    if item is Movie {
        movieCount += 1
    } else if item is Song {
        songCount += 1
    }
}

print("Media library contains \\(movieCount) movies and \\(songCount) songs")
// "Media library contains 2 movies and 3 songs" 출력

다운 캐스팅

특정 클래스 타입의 상수나 변수는 특정 서브클래스의 인스턴스를 참조하고 있을 수 있음

as? 와 as! 연산자를 이용해 어떤 타입의 인스턴스 인지 확인할 수 있음

as? 는 특정 타입이 맞는지 확신할 수 없을 때, as!는 확실한 경우에 사용 ( as! 사용했는데 지정 타입이 아니면 런타임 에러 )

for item in library {
    if let movie = item as? Movie {
        print("Movie: \\(movie.name), dir. \\(movie.director)")
    } else if let song = item as? Song {
        print("Song: \\(song.name), by \\(song.artist)")
    }
}

// Movie: Casablanca, dir. Michael Curtiz
// Song: Blue Suede Shoes, by Elvis Presley
// Movie: Citizen Kane, dir. Orson Welles
// Song: The One And Only, by Chesney Hawkes
// Song: Never Gonna Give You Up, by Rick Astley

캐스팅은 실제 인스턴스나 값을 바꾸는 것이 아닌, 지정한 타입으로 취급하는 것임

Any, AnyObject의 타입 캐스팅

스위프트에서는 두가지 특별한 타입이 제공됨

  • Any: 함수 타입을 포함해 모든 타입
  • AnyObject: 모든 클래스 타입의 인스턴스를 나타냄
var things = [Any]()

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
things.append({ (name: String) -> String in "Hello, \\(name)" })

for thing in things {
    switch thing {
    case 0 as Int:
        print("zero as an Int")
    case 0 as Double:
        print("zero as a Double")
    case let someInt as Int:
        print("an integer value of \\(someInt)")
    case let someDouble as Double where someDouble > 0:
        print("a positive double value of \\(someDouble)")
    case is Double:
        print("some other double value that I don't want to print")
    case let someString as String:
        print("a string value of \\"\\(someString)\\"")
    case let (x, y) as (Double, Double):
        print("an (x, y) point at \\(x), \\(y)")
    case let movie as Movie:
        print("a movie called \\(movie.name), dir. \\(movie.director)")
    case let stringConverter as (String) -> String:
        print(stringConverter("Michael"))
    default:
        print("something else")
    }
}

위의 예제에서 Int, Double 뿐 아니라 튜플, 함수도 Any 타입에 포함될 수 있다는 것 확인