티스토리 뷰

타입 캐스팅은 인스턴스의 타입을 확인하거나 슈퍼클래스나 서브클래스의 인스턴스를 그 부모-자식 관계에 있는 다른 클래스의 인스턴스로 취급하기 위한 방법입니다. 스위프트의 타입캐스팅은 is 와 as 로 구현할 수 있습니다. 타입 캐스팅을 통해 프로토콜을 준수하는지도 확인할 수 있습니다.

 

Defining a Class Hierarchy for Type Casting

같은 hierarchy(상속의 가계도라고 생각하면 됨)와 함께 타입 캐스팅을 사용하여 특정 클래스 인스턴스의 유형을 확인하고 해당 인스턴스를 동일한 계층 내의 다른 클래스로 캐스팅할 수 있습니다.

 

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")
]
// the type of "library" is inferred to be [MediaItem]

베이스 클래스인 MediaItem을 상속하는 Movie, Song 클래스가 있을 때

마지막 문단에서 library 상수는 스위프트의 타입 추정에 의해 Movie와 Song을 감싸안는 MediaItem 타입의 배열로 저장한다.

그러니까 만약에 library 상수 내의 배열값에 접근할 때 MediaItem으로 잡히기 때문에 원래 목적대로 사용하기 위해서는 다운캐스팅이 필요

 

Checking Type

is는 인스턴스가 서브클래스의 타입인지 확인하는데 사용합니다. 만약 그렇다면 true를 아니라면 false를 반환합니다.
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")
// Prints "Media library contains 2 movies and 3 songs"

is 연산자를 이용하여 movie와 song 개수를 체크해 주고 있다.

 

Downcasting

as? 또는 as! 연산자로 서브클래스 타입으로 다운캐스팅을 시도할 수 있습니다. 다운 캐스팅이 실패할 수 있기 때문에 2가지 형태로 주어집니다.
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

다운캐스팅을 통해 [MediaItem] 내부 요소들을 서브 클래스 타입으로 변환해서 내부 프로퍼티에 접근하고 있다.

 

Type Casting for Any and AnyObject

스위프트는 두가지  특별한 타입을 제공합니다. Any는 어떤 타입의 인스턴스이건 (함수 타입을 포함한) 표현할 수 있습니다.
AnyObject는 어떤 클래스 타입의 인스턴스이건 표현할 수 있습니다.
제공하는 동작과 기능이 명시적으로 필요한 경우에만 Any 및 AnyObject를 사용합니다. 코드에서 작업할 것으로 예상되는 유형을 구체적으로 지정하는 것이 항상 좋습니다.(2번째 예제)
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")
    }
}

// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of "hello"
// an (x, y) point at 3.0, 5.0
// a movie called Ghostbusters, dir. Ivan Reitman
// Hello, Michael

 

중첩 타입(내용이 별거 없어서 여기에 추가함)

Referring to Nested Types

let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol is "♡"

중첩 타입을 사용하려면 중첩된 순으로 선언해 줘야 한다.

'Swift Language Guide' 카테고리의 다른 글

Protocols(프로토콜)  (0) 2020.11.26
Extensions  (0) 2020.11.24
Error Handling(에러 핸들링)  (0) 2020.11.19
Optional Chaining(옵셔널 체이닝)  (0) 2020.11.18
11. 상속  (0) 2020.11.09
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함