[Swift] 타입캐스팅에 대해 알아보자!

zooneon·2020년 11월 19일
0

Swift 기본 문법

목록 보기
11/14
post-custom-banner

본 내용은 '스위프트 프로그래밍' 책을 학습한 후 이를 바탕으로 작성한 글입니다.

타입캐스팅

  • 스위프트에서는 다른 언어의 타입 변환 혹은 타입캐스팅 작업을 이니셜라이저로 단순화한다.
  • 스위프트의 타입캐스팅은 인스턴스의 타입을 확인하거나 자신을 다른 타입의 인스턴스처럼 동작할 수 있게 한다.
  • 스위프트의 타입캐스팅은 isas 연산자로 구현한다.
  • 이 두 연산자로 값의 타입을 확인하거나 다른 타입으로 전환할 수 있다.
  • 스위프트의 타입캐스팅은 참조 타입에서 주로 사용된다.

데이터 타입 확인

is 연산자

  • 타입 확인 연산자인 is를 사용하여 인스턴스가 어떤 클래스의 인스턴스인지 타입을 확인해볼 수 있다.
  • 인스턴스가 해당 클래스의 인스턴스거나 그 자식클래스의 인스턴스라면 true를 반환하고, 그렇지 않다면 false를 반환한다.
  • is 연산자는 클래스의 인스턴스뿐만 아니라 모든 데이터 타입에 사용할 수 있다.
class Coffee {
    let name: String
    let shot: Int
    
    var description: String {
        return "\(shot) shot \(name)"
    }
    
    init(shot: Int) {
        self.shot = shot
        self.name = "coffee"
    }
}

class Americano: Coffee {
    let iced: Bool
    
    override var description: String {
        return "\(shot) shot \(iced ? "iced" : "hot") americano"
    }
    
    init(shot: Int, iced: Bool) {
        self.iced = iced
        super.init(shot: shot)
    }
}

let coffee: Coffee = Coffee(shot: 1)
print(coffee.description)    //1 shot coffee

let americano: Americano = Americano(shot: 2, iced: true)
print(americano.description)    //2 shot iced americano

print(coffee is Coffee)    //true
print(coffee is Americano)    //false

print(americano is Coffee)    //true
print(americano is Americano)    //true

메타 타입 타입

  • 메타 타입 타입은 타입의 타입을 뜻한다.
  • 클래스, 구조체, 열거형의 이름은 타입의 이름이고 타입 이름 뒤에 .Type 을 붙이면 메타 타입을 나타낸다.
  • self를 사용하여 타입을 값처럼 표현할 수 있다.
protocol SomeProtocol { }
class SomeClass: SomeProtocol { }

let intType: Int.Type = Int.self
let stringType: String.Type = String.self
let classType: SomeClass.Type = SomeClass.self
let protocolType: SomeProtocol.Protocol = SomeProtocol.self

var someType: Any.Type

someType = intType
print(someType)    //Int

someType = stringType
print(someType)    //String

someType = classType
print(classType)    //SomeClass

someType = protocolType
print(protocolType)    //SomeProtocol

다운캐스팅

  • 자식클래스보다 더 상위에 있는 부모클래스의 타입을 자식클래스의 타입으로 캐스팅하는 것을 다운캐스팅이라고 한다.
  • 타입캐스트 연산자에는 as?as!가 있다.
  • 조건부 연산자인 as? 연산자는 다운캐스팅이 실패했을 경우 nil 을 반환하고, 다운캐스팅을 강제하는 as! 연산자는 다운캐스팅에 실패했을 경우 런타임 오류가 발생한다.
class Coffee {
    let name: String
    let shot: Int
    
    var description: String {
        return "\(shot) shot \(name)"
    }
    
    init(shot: Int) {
        self.shot = shot
        self.name = "coffee"
    }
}

class Americano: Coffee {
    let iced: Bool
    
    override var description: String {
        return "\(shot) shot \(iced ? "iced" : "hot") americano"
    }
    
    init(shot: Int, iced: Bool) {
        self.iced = iced
        super.init(shot: shot)
    }
}

let coffee: Coffee = Coffee(shot: 1)
let americano: Americano = Americano(shot: 2, iced: true)

if let actingOne: Americano = coffee as? Americano {
    print("This is Americano")
} else {
    print(coffee.description)
}
//1 shot coffee

if let actingOne: Coffee = coffee as? Coffee {
    print("This is just coffee")
} else {
    print(coffee.description)
}
//This is just coffee

if let actingOne: Americano = americano as? Americano {
    print("This is Americano")
} else {
    print(coffee.description)
}
//This is Americano

if let actingOne: Coffee = americano as? Coffee {
    print("This is just coffee")
} else {
    print(coffee.description)
}
//This is just coffee

Any, AnyObject의 타입캐스팅

  • Any는 함수 타입을 포함한 모든 타입을 뜻하고, AnyObject는 클래스 타입만을 뜻한다.
  • AnyAnyObject를 사용하면 예기치 못한 오류가 발생할 확률이 높아지므로 사용을 지양하는 것이 좋다.
func checkAnyType(of item: Any) {
    switch item {
    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:
        print("a positive double value of \(someDouble)")
    case let someString as String:
        print("a string value of \"\(someString)\"")
    case let stringConverter as (String) -> String:
        print(stringConverter("zooneon"))
    default:
        print("something else : \(type(of: item))")
    }
}

checkAnyType(of: 0)    //zero as an Int
checkAnyType(of: 0.0)    //zero as a Double
checkAnyType(of: 39)    //an Integer value of 39
checkAnyType(of: 3.14)    //a positive double value of 3.14
checkAnyType(of: "Hello")    //a string value of "Hello"
checkAnyType(of: { (name: String) -> String in "Hello, \(name)" })    //Hello, zooneon
profile
블로그 이전했습니다. https://blog.zooneon.dev
post-custom-banner

0개의 댓글