Swift : 제네릭 유형이 프로토콜을 준수하는지 확인
다음과 같이 정의한 프로토콜이 있습니다.
protocol MyProtocol {
...
}
또한 일반 구조체가 있습니다.
struct MyStruct <T> {
...
}
마지막으로 일반적인 기능이 있습니다.
func myFunc <T> (s: MyStruct<T>) -> T? {
...
}
T 유형이 MyProtocol을 준수하는지 함수 내부를 테스트하고 싶습니다. 본질적으로 나는 할 수 있기를 원합니다 (~ 의사 코드) :
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
. 지금까지 나는 아무데도 가지 않았다. 어떤 아이디어?
조금 늦었지만 테스트로 프로토콜에 응답하는지 테스트 할 수 있습니다 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
}
@Alex가 T
유형이 아닌 프로토콜을 준수 하는지 확인하고 싶습니다 s
. 그리고 일부 응답자는 명확하게 보지 못했습니다.
확인 T
유형은 다음과 같은 프로토콜을 따릅니다.
if let _ = T.self as? MyProtocol.Type {
// T conform MyProtocol
}
또는
if T.self is MyProtocol.Type {
// T conform MyProtocol
}
가장 간단한 대답은 : 그렇게하지 마십시오. 대신 오버로딩 및 제약 조건을 사용하고 런타임에 동적으로 테스트하는 대신 컴파일 타임에 모든 것을 미리 결정하십시오. 런타임 유형 검사 및 컴파일 타임 제네릭은 스테이크와 아이스크림과 비슷합니다. 둘 다 좋지만 혼합하는 것은 약간 이상합니다.
다음과 같은 것을 고려하십시오.
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
하지만 솔직히 말해서 일반 함수 내에서 그렇게해야합니까? 실제 유형이 무엇인지 확실하지 않은 경우 더 나은 옵션은 나중에 지연하고 알아 내기 위해 제네릭 함수 내에서 찌르는 것보다 미리 파악하는 것입니다.
여러 유형의 케이스를 처리하려는 경우 swift의 스위치 케이스 패턴 일치를 활용할 수도 있습니다 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
...
}
}
You need declare protocol as @objc
:
@objc protocol MyProtocol {
...
}
From Apple's "The Swift Programming Language" book:
You can check for protocol conformance only if your protocol is marked with the @objc attribute, as seen for the HasArea protocol above. This attribute indicates that the protocol should be exposed to Objective-C code and is described in Using Swift with Cocoa and Objective-C. Even if you are not interoperating with Objective-C, you need to mark your protocols with the @objc attribute if you want to be able to check for protocol conformance.
Note also that @objc protocols can be adopted only by classes, and not by structures or enumerations. If you mark your protocol as @objc in order to check for conformance, you will be able to apply that protocol only to class types.
let conforms = T.self is MyProtocol.Type
참고URL : https://stackoverflow.com/questions/28124684/swift-check-if-generic-type-conforms-to-protocol
'Nice programing' 카테고리의 다른 글
부울이 null인지 Java 확인 (0) | 2020.11.29 |
---|---|
게시 요청에서 JAX-RS 클라이언트의 응답 본문 읽기 (0) | 2020.11.29 |
Android Studio에서 대상 에뮬레이터를 변경하는 방법은 무엇입니까? (0) | 2020.11.29 |
Typescript에서 키-값 쌍을 사용할 수 있습니까? (0) | 2020.11.29 |
컴퓨터에서 실행되는 SQL Server 버전을 어떻게 알 수 있습니까? (0) | 2020.11.29 |