[swift] 타입 캐스팅

타입 캐스팅(Type Casting)은 스위프트에서 객체의 타입을 확인하거나 다른 타입으로 변환하는 방법을 말합니다. 이는 클래스와 프로토콜 타입 간의 타입 변환 뿐만 아니라 스위프트의 타입 시스템에서 다루는 모든 유형에 적용될 수 있습니다.

타입 캐스팅은 다음 두 가지 방법으로 수행할 수 있습니다.

1. is 연산자를 사용한 타입 확인

is 연산자를 사용하여 변수나 상수의 타입을 확인할 수 있습니다. 이 연산자는 해당 객체가 지정된 타입의 인스턴스인지 여부를 불리언(Boolean) 값으로 반환합니다. 예를 들어, 다음과 같은 코드를 살펴보겠습니다.

class Animal {
    func makeSound() {
        print("Animal is making a sound")
    }
}

class Dog: Animal {
    func bark() {
        print("Dog is barking")
    }
}

class Cat: Animal {
    func meow() {
        print("Cat is meowing")
    }
}

let dog = Dog()
let cat = Cat()

print(dog is Animal) // true
print(cat is Animal) // true
print(dog is Cat)    // false
print(cat is Dog)    // false

위의 코드는 Animal, Dog, Cat 클래스를 정의하고, dogcat 객체를 생성합니다. is 연산자를 사용하여 Animal 타입인지, Cat 타입인지 확인할 수 있습니다. 결과 값에 따라 true 또는 false가 출력됩니다.

2. as 연산자를 사용한 타입 변환

as 연산자를 사용하여 객체를 다른 타입으로 변환할 수 있습니다. 이는 상속 관계에 있는 클래스 간에 타입을 변환하거나, 프로토콜을 구현한 객체를 해당 프로토콜 타입으로 변환할 때 유용합니다. 다음은 as 연산자의 사용 예시입니다.

2-1. Upcasting

Upcasting은 서브클래스 객체를 슈퍼클래스 타입으로 변환하는 것을 의미합니다. 이는 자식 클래스의 메서드와 프로퍼티에 접근할 수 없게 됩니다. 다음과 같은 코드를 살펴보겠습니다.

let dog = Dog()
let animal: Animal = dog

animal.makeSound()
// animal.bark() // 오류: 'Animal'에는 'bark'가 없습니다

위의 코드에서 dog 객체는 Dog 타입이고, animal 변수는 Animal 타입입니다. dog 객체를 animal 변수에 할당하여 Upcasting을 수행한 후, makeSound() 메서드를 호출할 수 있지만 bark() 메서드에는 접근할 수 없습니다.

2-2. Downcasting

Downcasting은 슈퍼클래스 타입을 서브클래스 타입으로 변환하는 것을 의미합니다. 이는 Upcasting과 다르게 명시적으로 타입을 지정해야 합니다. 타입 캐스트 연산자 as? 또는 as!를 사용하여 downcast를 수행할 수 있습니다. 다음은 as?as!의 사용 예시입니다.

as?

as?는 Optional 타입으로 반환되며, 타입 변환이 실패할 경우 nil을 반환합니다. 따라서 반환된 값은 옵셔널 타입으로 해제해야 합니다. 다음은 as?를 사용한 예시입니다.

let animal: Animal = Dog()

if let dog = animal as? Dog {
    dog.bark()
} else {
    print("Cannot downcast to Dog")
}

if let cat = animal as? Cat {
    cat.meow()
} else {
    print("Cannot downcast to Cat")
}

위의 코드에서 animal 변수는 Animal 타입인데, 이를 as?를 사용하여 Dog 타입으로 타입 변환하고 bark() 메서드를 호출합니다. 타입 변환이 실패하면 else 블록의 코드가 실행됩니다.

as!

as!는 강제 언래핑(Force Unwrapping)하여 타입 변환하며, 타입 변환이 실패할 경우 런타임 오류(Runtime Error)가 발생합니다. 따라서 타입이 변환되지 않을 것을 확신할 때만 사용해야 합니다. 다음은 as!를 사용한 예시입니다.

let animal: Animal = Dog()

let dog = animal as! Dog
dog.bark()

let cat = animal as! Cat // 런타임 오류: 'Cat'으로 상수 캐스팅이 실패하였습니다

위의 코드에서 animal 변수는 Animal 타입인데, as!를 사용하여 Dog 타입으로 타입 변환한 후 bark() 메서드를 호출합니다. 다음 줄은 as!를 사용하여 Cat 타입으로 타입 변환하려고 시도하는데, 변환이 실패하여 런타임 오류가 발생합니다.

결론

타입 캐스팅은 스위프트에서 객체의 타입을 다루는 중요한 기능입니다. is 연산자를 사용하여 타입을 확인하고, as 연산자를 사용하여 타입을 변환하는 간단한 방법을 알아보았습니다. 이러한 타입 캐스팅 기능을 적절하게 활용하여 프로그램을 보다 유연하고 확장 가능하게 구현할 수 있습니다.

참고 문서: The Swift Programming Language - Type Casting