[Swift] Type Casting(타입 캐스팅) 사용법 & 예제

728x90

Type Casting(타입 캐스팅) 사용법 & 예제


Type Casting(타입 캐스팅) 이란?

  • 인스턴스의 타입을 확인 하거나, 인스턴스의 타입을 슈퍼 클래스 혹은 서브 클래스타입처럼 다루기 위해 사용합니다.
  • Swift에서의 타입 캐스팅은 ‘is’ 와 ’as’ 라는 연산자로 구현할 수 있으며, 이 두 연산자는 값의 타입을 확인하거나 다른 타입으로 변환하는 간단한 방법을 제공합니다.

사용 예제

Defining a Class Hierarchy for Type Casting

[예제1]
타입 캐스팅을 활용하여 특정 클래스 인스턴스의 타입을 확인

class Person {
    var name: String

    //초기값이 업으므로 init 만들어준다
    init(name: String) {
        self.name = name
    }
}

var zedd = Person(name: "Zedd")

//인스턴스가 Person의 인스턴스인가?를 확인
if zedd is Person {
    print(true)
}

//인스턴스의 프로퍼티도 확인 가능
if zedd.name is String {
    print(true)
}

[예제2]
인스턴스 타입을 확인하여 그 값의 개수를 출력

import Foundation

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)
    }
}

//자연스럽게 MediaItem 타입의 배열이 됩니다.
let library = [
    Movie(name: "죽은 시인의 사회", director: "피터 위어"),
    Song(name: "창공", artist: "김철수"),
    Movie(name: "인터스텔라", director: "크리스토퍼 놀란"),
    Movie(name: "공범자들", director: "최승호")
]

//MARK: 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 libaray는 \(movieCount)개 영화와 \(songCount)개의 노래가 있습니다. ")

 

 

Downcasting

특정 클래스 타입의 상수 또는 변수는 하위 클래스의 인스턴스를 참조 할 수 있습니다.

다운 캐스팅은 실패 할 가능성도 있기 때문에 두가지 형태로 제공됩니다.

  1. 조건부 형식인 as? : 다운 캐스팅 하려는 타입의 Optional 값을 반환 합니다.
  2. 강제 형식인 as! : 강제 언래핑을 하여 값을 반환 합니다.

-> 따라서 다운캐스팅이 반드시 성공할 거라는 확신이 들때만 !을 사용
이 형식은 오류 발생하면 런타임 에러 발생

//library[MediaItem]의 배열의 안의 인스턴스는 서브클래스인 Movie 와 Song이기 때문에 다운캐스팅 된 것이다.
//이 일련의 과정이 as로 가능해 진다. (super클래스의 sub클래스의 캐스팅)
for item in library {

    if let movie = item as? Movie { //?옵셔널 이기 때문에 if문 사용

        print("Movie: \(movie.name), dir. \(movie.director)")
    }
}

 

 

Type Casting for Any and AnyObject

Swift는 특별한 타입을 제공합니다.

  1. Any : function타입을 포함한 모든 타입의 인스턴스 표현 가능
  2. AnyObject : 모든 ‘클래스’ 타입의 인스턴스 표현 가능

하지만 이 두가지 표현은 꼭 필요할때 사용하는 것이 좋습니다.
왜냐하면 코드에서 처리할 타입은 항상 구체적으로 적는 것이 좋기 때문입니다.

print("Media libaray는 \(movieCount)개 영화와 \(songCount)개의 노래가 있습니다. ")

var things = [Any]()

things.append(0)

things.append(0.0)

things.append(42)

things.append(3.14158)

things.append("hello")

things.append((3.0,5.0))

things.append(Movie(name: "타짜", director: "이원태"))

things.append({(name: String) -> String in "Hello, \(name)"})

위의 코드처럼 모든 타입을 다 넣을 수 있는 것이 Any 타입입니다.

  • 아래는 as / as? , as! 의 차이점에 대해 알아 보겠습니다.
  • 이 둘의 차이는 실행되는 시간의 차이인데요 , as는 컴파일 타임에 , as? as!는 런타임에 실행된다고 합니다.
  • 아래의 예제처럼 업 캐스팅과 패턴패칭(switch)에서만 사용할 수 있습니다.
for thing in things {

    switch thing {

    case 0 as Int:
        print("Int Type 0")
    case 0 as Double:
        print("Double Type 0")
    case let someInt as Int:
        print("0이 아닌 Int \(someInt)")
    case let someDouble as Double where someDouble > 0:
        print("양의 Double Type \(someDouble)")
    case is Double:
        print("다른 Double들은 출력하고 싶지 않네..")
    case let someString as String:
        print("String값은 \"\(someString)\"")
    case let (x, y) as (Double, Double):
        print("x와 y좌표는 \(x), \(y)")
    case let movie as Movie:
        print("영화 이름은 \(movie.name), dir. \(movie.director)")
    case let stringConverter as (String) -> (String):
        print(stringConverter("미카엘"))
    default:
        print("다른 것")

    }
}

 

출처 : Swift ) Type Casting
728x90

댓글

Designed by JB FACTORY