Swift:检查genericstypes是否符合协议

我有一个协议,我这样定义:

protocol MyProtocol { ... } 

我也有一个通用的结构:

 struct MyStruct <T> { ... } 

最后我有一个通用的function:

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

如果Ttypes符合MyProtocol,我想在函数内部进行testing。 本质上我想能够做到(〜伪代码):

 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.selfT is MyProtocol ,用==代替is 。 到目前为止,我没有得到任何地方。 有任何想法吗?

有点晚,但你可以testing是否有什么东西响应协议与as ? testing:

 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 } 

最简单的答案是:不要这样做。 相反,使用重载和约束,并在编译时预先确定所有的东西,而不是在运行时dynamic地testing东西。 运行时types检查和编译时generics就像牛排和冰淇淋 – 两者都很好,但混合起来有点奇怪。

考虑这样的事情:

 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在运行时支持协议,则不能dynamicbuild立:

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

但是,诚实地说,你真的需要在你的generics函数中这么做吗? 如果你不确定什么是实际的types,那么更好的select可能是预先计算出来,而不是稍后推迟,并在一个通用函数中找出它来找出结果。

我不得不说,@Alex想要检查Ttypes是否符合协议而不是s 。 还有一些回答者没有看清楚。

检查T型符合这样的协议:

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

要么

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

你也可以利用swift的switch case模式匹配 ,如果你想处理多个Ttypes的情况:

 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 { ... } 

从苹果的“Swift编程语言”一书中:

只有在协议标记为@objc属性时才能检查协议一致性,如上面的HasArea协议所示。 这个属性表明该协议应该暴露给Objective-C代码,在使用Cocoa和Objective-C的Swift中有描述。 即使您不与Objective-C进行互操作,如果您希望能够检查协议一致性,您也需要使用@objc属性标记您的协议。

还要注意,@objc协议只能由类来采用,而不能通过结构或枚举。 如果您将协议标记为@objc以检查一致性,您将只能将该协议应用于类types。