![](/img/trans.png)
[英]How to implement conditional conformance of a generic to a protocol in a function?
[英]Workaround for conditional conformance in Swift (was: Adding protocol to a constrained generic types)
下面的代码段演示了我要解决的问题。
import Foundation
protocol Printable {
func className() -> String
}
class SomeType: Printable {
func className() -> String {
return "SomeType"
}
}
class List<T> {
}
extension List where T: SomeType {
func className() -> String {
return "List<SomeType>"
}
}
func test(type: Any, message: String) {
guard type is Printable else {
print("\(message): ERROR")
return
}
print("\(message): SUCCESS")
}
let s: Any = SomeType()
test(type: s, message: "#1")
let slist1: Any = List<Any>()
test(type: slist1, message: "#2")
let slist2: Any = List<SomeType>()
test(type: slist2, message: "#3")
我怎么能得到这个:
> #1: SUCCESS <--- as expected
> #2: ERROR <--- it's okay
> #3: SUCCESS <--- I am getting ERROR instead
似乎向该行添加协议可以解决问题:
extension List: Printable where T: SomeType { // COMPILE ERROR
但不幸的是,这是不允许的。
另一种方法是使用:
extension List where T: Printable { // COMPILES OK in Swift 2.3 but doesn't work. COMPILE ERROR in Swift 3.0
但是同样,没有运气通过测试。
我还可以做些什么来将协议添加到受约束的泛型类型?
好吧,在您的警惕下,您要问“如果这是可打印的,那么打印成功,否则打印错误”,在第一个示例中,您有s,它是可以打印的SomeType。 没关系。
之后,您将拥有类型为List<Any>
slist1,该List<Any>
绝对不是可打印的类型,并且会出现“错误”。 没关系
接下来,您有了List<SomeType>
。 现在您有了一个类扩展,将T定义为SomeType,对吗? 但是您只是将T定义为SomeType而不是实际的List,因此当您将整个List传递给测试函数时,您将无法通过测试,因为List<AnyTypeHere>
无法打印,因为列表本身没有没有实现Printable。
现在的问题是,您是否希望整个列表都可打印? 如果是这样,则只需使其符合SomeType或Printable协议即可。 除了将单个List<SomeType>
元素传递到函数中之外,这是传递它的唯一方法。 您的函数逻辑是正确的,但这只是对该概念的滥用。
因此,如果您希望List<SomeType>
通过该传递,则可以执行类似的操作
class List<T> : Printable where T:SomeType {
//Add code here that conforms to protocol
}
这样做将使您的第二次测试失败,因为Any不会从SomeType继承,但是它将使您的第三次测试通过,因为现在List<T>
是Printable且T的类型也是SomeType。 我的意思是,这只是一种获取所需外观的快速方法。 除非您添加其他内容,否则您将不会同时通过第二个和第三个测试,因为第二个测试是List的类型为Any,而第三个测试的List的类型为Printable。 因此,其中之一将引发错误(因为List的类型不是Printable)或所有测试都显示成功(因为List的类型是Printable)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.