繁体   English   中英

Swift中条件一致性的解决方法(是:将协议添加到受约束的泛型类型中)

[英]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)

现在有了Swift 4.2,这是一个更新的答案,现在将条件一致性添加为功能。

从他们在Github上规范来看,这种代码现在有效

   extension List : Printable where T: SomeType {
       func className() -> String {
           return "List<SomeType>"
       }
   }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM