programing

Swift: 제네릭 형식이 프로토콜을 준수하는지 확인합니다.

i4 2023. 8. 9. 20:29
반응형

Swift: 제네릭 형식이 프로토콜을 준수하는지 확인합니다.

다음과 같이 정의한 프로토콜이 있습니다.

protocol MyProtocol {
   ...
}

일반적인 구조도 가지고 있습니다.

struct MyStruct <T>  {
    ...
}

마지막으로 일반적인 기능이 있습니다.

func myFunc <T> (s: MyStruct<T>) -> T? {
   ...
}

T형이 My Protocol과 일치하는지 함수 내부를 테스트하고 싶습니다.기본적으로 저는 다음을 할 수 있기를 원합니다(~ 의사 코드).

let conforms = T.self is MyProtocol

그러나 이 경우 컴파일러 오류가 발생합니다.

error: cannot downcast from 'T.Type' to non-@objc protocol type 'MyProtocol'
   let conforms = T.self is MyProtocol
                  ~~~~~~ ^  ~~~~~~~~~~

나는 또한 변형을 시도했습니다, 예를 들면.T.self is MyProtocol.self,T is MyProtocol및 사용==대신에is지금까지 저는 아무 데도 가지 못했습니다.아이디어 있어요?

나는 @알렉스가 확인하고 싶다고 말해야 합니다.T형식이 프로토콜을 준수하지 않습니다.s그리고 어떤 대답자는 명확하게 보지 못했습니다.

확인.Ttype은 다음과 같은 프로토콜을 준수합니다.

if let _ = T.self as? MyProtocol.Type {
    //  T conform MyProtocol
}

또는

if T.self is MyProtocol.Type {
    //  T conform MyProtocol
}

조금 늦었지만 프로토콜에 응답하는지 테스트할 수 있습니다.as ?테스트:

if let currentVC = myViewController as? MyCustomProtocol {
    // currentVC responds to the MyCustomProtocol protocol =]
}

편집: 조금 더 짧습니다.

if let _ = self as? MyProtocol {
    // match
}

그리고 가드를 사용합니다.

guard let _ = self as? MyProtocol else {
    // doesn't match
    return
}

가장 간단한 대답은: 그렇게 하지 마세요.대신 오버로드 및 제약 조건을 사용하고 런타임에 동적으로 항목을 테스트하는 대신 컴파일 시간에 모든 것을 미리 결정합니다.런타임 유형 검사와 컴파일 타임 제네릭은 스테이크와 아이스크림과 같습니다. 둘 다 좋지만 혼합하는 것은 약간 이상합니다.

다음과 같은 것을 생각해 보십시오.

protocol MyProtocol { }

struct MyStruct <T>  { let val: T }

func myFunc<T: MyProtocol>(s: MyStruct<T>) -> T? {
    return s.val
}

func myFunc<T>(s: MyStruct<T>) -> T? {
    return nil
}

struct S1: MyProtocol { }
struct S2 { }

let m1 = MyStruct(val: S1())
let m2 = MyStruct(val: S2())

myFunc(m1) // returns an instance of S1
myFunc(m2) // returns nil, because S2 doesn't implement MyProtocol

단점은 T가 런타임에 프로토콜을 지원한다면 동적으로 설정할 수 없다는 것입니다.

let o: Any = S1()
let m3 = MyStruct(val: o)
myFunc(m3)  // will return nil even though o 
            // does actually implement MyProtocol

하지만 솔직히 말해서, 당신은 당신의 일반적인 기능 안에서 그것을 할 필요가 있습니까?실제 유형이 무엇인지 확신할 수 없는 경우에는 나중으로 미루고 일반적인 기능 안에서 확인하는 것보다 사전에 확인하는 것이 더 나은 옵션일 수 있습니다.

Let complicates = T.self는 My Protocol입니다.유형

여러 유형의 사례를 처리하려면 스위프트의 스위치 케이스 패턴 매칭을 활용할 수도 있습니다.T:

func myFunc<T>(s: MyStruct<T>) -> T? {
    switch s {
    case let sType as MyProtocol:
        // do MyProtocol specific stuff here, using sType
    default:
        //this does not conform to MyProtocol
    ...
    }
}

프로토콜을 다음과 같이 선언해야 합니다.@objc:

@objc protocol MyProtocol {
    ...
} 

Apple의 "The Swift Programming Language" 책에서:

위의 HasArea 프로토콜에 표시된 것처럼 프로토콜이 @objc 특성으로 표시된 경우에만 프로토콜 준수를 확인할 수 있습니다.이 속성은 프로토콜이 목표-C 코드에 노출되어야 함을 나타내며, 코코아 및 목표-C와 함께 스위프트 사용에 설명되어 있습니다.Objective-C와 상호 운용되지 않는 경우에도 프로토콜 준수를 확인하려면 @objc 속성으로 프로토콜을 표시해야 합니다.

또한 @objc 프로토콜은 구조체나 열거형이 아닌 클래스에서만 채택할 수 있습니다.규정 준수를 확인하기 위해 프로토콜을 @objc로 표시하면 해당 프로토콜을 클래스 유형에만 적용할 수 있습니다.

테스트 사례의 경우 다음과 같이 적합성을 확인합니다.

let conforms: Bool = (Controller.self as Any) is Protocol.Type

현대적인 답변은 다음과 같습니다. (Swift 5.1)

func myFunc < T: MyProtocol> (s: MyStruct<T>) -> T? {    ... }

언급URL : https://stackoverflow.com/questions/28124684/swift-check-if-generic-type-conforms-to-protocol

반응형