클래스 및 하위 클래스의 계층 구조와 함께 Type Casting을 사용하여 특정 클래스 인스턴스의 유형을 확인하고 해당 인스턴스를 동일한 계층 구조 내의 다른 클래스로 캐스팅할 수 있습니다.
아래의 세 가지 코드 조각은 Type Casting의 예에서 사용하기 위해 클래스의 계층 구조와 해당 클래스의 인스턴스를 포함하는 배열을 정의합니다.
첫 번째 소스 코드은 MediaItem이라는 새 기본 클래스를 정의합니다. 이 클래스는 디지털 미디어 라이브러리에 나타나는 모든 종류의 항목에 대한 기본 기능을 제공합니다.
특히, String 유형의 이름 속성과 초기화 이름 이니셜라이저를 선언합니다. (모든 영화와 Song를 포함한 모든 미디어 항목에는 이름이 있다고 가정합니다.)
class MediaItem {
var name: String
init(name: String) {
self.name = name
}
}
다음 소스 코드은 MediaItem의 두 하위 클래스를 정의합니다. 첫 번째 하위 클래스인 Movie는 영화나 영화에 대한 추가 정보를 캡슐화합니다
해당 이니셜라이저와 함께 기본 MediaItem 클래스 위에 director 속성을 추가합니다. 두 번째 하위 클래스인 Song은 기본 클래스 위에 아티스트 속성과 초기화 프로그램을 추가합니다.
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)
}
}
마지막 소스 코드은 2개의 Movie 인스턴스와 3개의 Song 인스턴스를 포함하는 library라는 상수 배열을 생성합니다.
라이브러리 배열의 유형은 배열 리터럴의 내용으로 초기화하여 유추됩니다.
Swift의 유형 검사기는 Movie와 Song이 MediaItem의 공통 수퍼클래스를 가지고 있다는 것을 추론할 수 있으므로 라이브러리 배열에 대해 [MediaItem] 유형을 유추합니다.
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]
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"
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
캐스팅은 실제로 인스턴스를 수정하거나 값을 변경하지 않습니다. 기본 인스턴스는 동일하게 유지됩니다. 그것은 단순히 그것이 캐스트 된 유형의 인스턴스로 취급되고 액세스됩니다.
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
모든 유형은 선택적 유형을 포함하여 모든 유형의 값을 나타냅니다. Swift는 Any 유형의 값이 예상되는 선택적 값을 사용하는 경우 경고를 표시합니다.
선택적 값을 Any 값으로 사용해야 하는 경우 아래와 같이 as 연산자를 사용하여 선택적 값을 Any로 명시적으로 캐스팅할 수 있습니다.let optionalNumber: Int? = 3 things.append(optionalNumber) // Warning things.append(optionalNumber as Any) // No warning