🔥 다운캐스팅
특정 클래스 타입의 상수나 변수가 실제로는 서브클래스의 인스턴스를 참조하고 있을 수 있어요. 이런 경우라고 생각되면, as?
또는 as!
연산자를 사용하여 서브클래스 타입으로 다운캐스트
를 시도해볼 수 있지요.
다운캐스팅은 실패할 수 있기 때문에, 타입 캐스트 연산자에는 두 가지 다른 형식이 있어요. 조건부 형식인 as?
는 다운캐스트하려는 타입의 옵셔널 값을 반환하고, 강제 형식인 as!
는 다운캐스트를 시도하고 결과를 단일 복합 동작으로 강제 언래핑합니다.
다운캐스트가 성공할지 확신할 수 없을 때는 타입 캐스트 연산자의 조건부 형식(as?
)을 사용하세요. 이 형식의 연산자는 항상 옵셔널 값을 반환할 거예요. 만약 다운캐스트가 불가능하다면 이 값은 nil
이 될 거랍니다. 이를 통해 다운캐스트의 성공 여부를 확인할 수 있지요.
다운캐스트가 항상 성공할 거라고 확신할 때만 타입 캐스트 연산자의 강제 형식(as!
)을 사용하세요. 잘못된 클래스 타입으로 다운캐스트를 시도하면 이 형식의 연산자는 런타임 오류를 발생시킬 거예요.
아래 예제는 library
의 각 MediaItem
을 순회하면서, 각 항목에 대한 적절한 설명을 출력해요. 이를 위해서는 각 항목을 진짜 Movie
나 Song
으로 접근해야 하고, 단순히 MediaItem
으로 접근해서는 안 됩니다. 설명에 사용하기 위해 Movie
의 director
속성이나 Song
의 artist
속성에 접근하려면 이것이 필요하지요.
이 예제에서 배열의 각 항목은 Movie
일 수도 있고 Song
일 수도 있어요. 각 항목에 대해 실제로 어떤 클래스를 사용해야 할지 미리 알 수 없기 때문에, 루프를 돌 때마다 조건부 형식의 타입 캐스트 연산자(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
swift
이 예제는 먼저 현재 item
을 Movie
로 다운캐스트하려고 시도해요. item
은 MediaItem
인스턴스이기 때문에 Movie
일 가능성이 있어요. 마찬가지로 Song
일 수도 있고, 심지어 그냥 기본 MediaItem
일 수도 있지요. 이런 불확실성 때문에, 서브클래스 타입으로 다운캐스트를 시도할 때 as?
형식의 타입 캐스트 연산자는 옵셔널
값을 반환합니다. item as? Movie
의 결과는 Movie?
, 즉 "옵셔널 Movie
" 타입이에요.
라이브러리 배열의 Song
인스턴스에 적용되면 Movie
로의 다운캐스팅은 실패해요. 이를 처리하기 위해, 위의 예제는 옵셔널 바인딩을 사용하여 옵셔널 Movie
에 실제로 값이 포함되어 있는지(즉, 다운캐스트가 성공했는지) 확인하고 있어요. 이 옵셔널 바인딩은 "if let movie = item as? Movie
"로 작성되는데, 이는 다음과 같이 읽을 수 있지요:
"item
을 Movie
로 접근하려고 시도해봐. 만약 이것이 성공하면, 반환된 옵셔널 Movie
에 저장된 값을 movie
라는 새로운 임시 상수에 설정해."
만약 다운캐스팅이 성공하면, movie
의 속성들이 해당 Movie
인스턴스에 대한 설명을 출력하는 데 사용되는데, 여기에는 director
의 이름도 포함돼요. Song
인스턴스를 확인하고 라이브러리에서 Song
이 발견될 때마다 적절한 설명(artist
이름 포함)을 출력하는 데에도 유사한 원리가 사용됩니다.
이처럼 다운캐스팅은 런타임에 인스턴스의 실제 타입을 확인하고 해당 타입에 맞는 속성과 메서드에 접근하는 데 매우 유용해요. 하지만 항상 옵셔널 바인딩을 사용하여 다운캐스팅의 성공 여부를 확인해야 한다는 점을 기억하세요. 그렇지 않으면 런타임 오류가 발생할 수 있답니다!
아래는 다운캐스팅이 어떻게 작동하는지 보여주는 플로우차트예요.
이 플로우차트는 MediaItem
인스턴스에서 시작해서, 먼저 Movie
로의 다운캐스트를 시도해요. 만약 성공하면 Movie
속성에 접근할 수 있지요. 실패하면 Song
으로의 다운캐스트를 시도하고, 성공 시 Song
속성에 접근합니다. 두 다운캐스트 모두 실패하면 다운캐스팅이 실패한 것으로 간주되지요.