🔥 프로토콜 준수 여부 확인하기

447자
6분

Swift에서는 isas 연산자를 사용하여 프로토콜 준수 여부를 확인하고, 특정 프로토콜로 캐스팅할 수 있습니다. 프로토콜에 대한 확인 및 캐스팅은 Type Casting에서 설명한 유형에 대한 확인 및 캐스팅과 정확히 동일한 구문을 따릅니다.

  • is 연산자는 인스턴스가 프로토콜을 준수하면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
  • as? 버전의 다운캐스트 연산자는 프로토콜 유형의 옵셔널 값을 반환하며, 인스턴스가 해당 프로토콜을 준수하지 않으면 이 값은 nil입니다.
  • as! 버전의 다운캐스트 연산자는 프로토콜 유형으로 다운캐스트를 강제로 수행하며, 다운캐스트가 성공하지 않으면 런타임 오류가 발생합니다.

다음 예제에서는 HasArea라는 프로토콜을 정의하며, 이 프로토콜은 area라는 이름의 읽기 가능한 Double 속성을 요구합니다.

protocol HasArea {
    var area: Double { get }
}
swift

다음은 HasArea 프로토콜을 준수하는 CircleCountry 두 개의 클래스입니다.

class Circle: HasArea {
    let pi = 3.1415927
    var radius: Double
    var area: Double { return pi * radius * radius }
    init(radius: Double) { self.radius = radius }
}
 
class Country: HasArea {
    var area: Double
    init(area: Double) { self.area = area }
}
swift

Circle 클래스는 저장 속성인 radius를 기반으로 계산 속성으로 area 속성 요구사항을 구현합니다. Country 클래스는 저장 속성으로 직접 area 요구사항을 구현합니다. 두 클래스 모두 HasArea 프로토콜을 올바르게 준수합니다.

다음은 HasArea 프로토콜을 준수하지 않는 Animal이라는 클래스입니다.

class Animal {
    var legs: Int
    init(legs: Int) { self.legs = legs }
}
swift

Circle, Country, Animal 클래스는 공유 기본 클래스를 가지고 있지 않습니다. 그럼에도 불구하고 모두 클래스이므로 세 가지 유형의 인스턴스를 모두 사용하여 AnyObject 유형의 값을 저장하는 배열을 초기화할 수 있습니다.

let objects: [AnyObject] = [
    Circle(radius: 2.0),
    Country(area: 243_610),
    Animal(legs: 4)
]
swift

objects 배열은 반지름이 2인 Circle 인스턴스, 영국의 표면적(제곱 킬로미터)으로 초기화된 Country 인스턴스, 다리가 4개인 Animal 인스턴스를 포함하는 배열 리터럴로 초기화됩니다.

이제 objects 배열을 반복하고, 배열의 각 객체가 HasArea 프로토콜을 준수하는지 확인할 수 있습니다.

for object in objects {
    if let objectWithArea = object as? HasArea {
        print("Area is \(objectWithArea.area)")
    } else {
        print("Something that doesn't have an area")
    }
}
// Area is 12.5663708
// Area is 243610.0
// Something that doesn't have an area
swift

배열의 객체가 HasArea 프로토콜을 준수할 때마다 as? 연산자가 반환하는 옵셔널 값은 objectWithArea라는 상수로 옵셔널 바인딩을 통해 언래핑됩니다. objectWithArea 상수는 HasArea 유형으로 알려져 있으므로 area 속성에 안전하게 액세스하여 출력할 수 있습니다.

캐스팅 프로세스에 의해 기본 객체가 변경되지 않는다는 점에 유의하세요. 객체는 여전히 Circle, Country, Animal입니다. 그러나 objectWithArea 상수에 저장되는 시점에는 HasArea 유형으로만 알려져 있으므로 area 속성에만 액세스할 수 있습니다.

lecture image

위의 다이어그램은 objects 배열의 각 객체에 대해 HasArea 프로토콜 준수 여부를 확인하고, 프로토콜을 준수하는 경우 objectWithArea 상수에 할당하여 area 속성에 접근하는 과정을 보여줍니다. 프로토콜을 준수하지 않는 경우에는 해당 메시지를 출력합니다.

이처럼 프로토콜은 다양한 유형의 객체를 공통의 인터페이스로 처리할 수 있게 해주는 강력한 기능입니다. isas 연산자를 사용하여 프로토콜 준수 여부를 확인하고 캐스팅함으로써 코드의 유연성과 재사용성을 높일 수 있습니다.