관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift 공식 문서] 18. Type Casting (타입 캐스팅, 다운캐스팅, 업캐스팅) 본문

swift 공식 문서

[iOS - swift 공식 문서] 18. Type Casting (타입 캐스팅, 다운캐스팅, 업캐스팅)

jake-kim 2021. 7. 15. 22:15

Type Casting

  • instance의 유형을 확인하거나 해당 instance를 자체 클래스 계층 구조에서 superclass또는 subclass로 처리하는 방법
  • 연산자는 두가지: is와 as

Type 확인

  • is연산자 사용: 좌측엔 instance, 우측엔 type
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)
    }
}

// upcasting: 타입은 superclass이지만 instance는 subclass
let library = [
    Movie(name: "name1", director: "dir1"),
    Song(name: "name2", artist: "art1"),
    Movie(name: "name3", director: "dir2")
]

var movieCount = 0
var songCount = 0
library.forEach { item in
    if item is Movie {
        movieCount += 1
    } else if item is Song {
        songCount += 1
    }
}

print(movieCount) // 2
print(songCount) // 1

Downcasting

  • type은 superlcass지만 subclass의 인스턴스로 type 변경
  • 연산자는 두 가지 존재
    • as?
    • as!
// Type은 MediaItem이지만 subclass인 movie와 song으로 downcasting

library.forEach { item in
    if let movie = item as? Movie {
        print("movie: \(movie.name)")
    } else if let song = item as? Song {
        print("song: \(song.name)")
    }
}

Upcasting

  • type은 subclass지만 superclass의 인스턴스로 type 변경
  • as 사용, 무조건 성공 (subclass 타입을 superclass로 변경하는 것이므로)
  • as와 is 차이 주의
    • is는 instance타입을 확인하는데 사용
    • as는 type casting에 사용
let exTeacher: Teacher = Teacher(year: 2021, name: "abc")
let exHuman: Human = Human(name: "a")

/// upcasting: subclass instance를 superclass 타입으로 변경
let human: Human = exTeacher as Human /// 업캐스팅

/// downcasting: superclass instance를 subclass 타입으로 변경
let teacher: Teacher? = exHuman as? Teacher

Any, AnyObject에 대한 Type casting

  • Any와 AnyObject 타입을 사용할 경우, 상속 관계가 아니어도 예외적으로 type casting 사용 가능
    • 개념 주의: 부모 타입을 자식 타입으로 변경하는 것이므로 downcasting인것 같지만, as로 사용하는 것을 주의
  • Any: 모든 type을 포함하여 모든 유형의 instance 나타낼 수 있는 것
  • AnyObject: 모든 class type의 instance 표현
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")
    }
}

* 참고

https://docs.swift.org/swift-book/LanguageGuide/TypeCasting.html

Comments