Element == StringProtocol 和 Element: StringProtocol 有什么区别?

Mar*_*eIV 2 swift swift-extensions swift4

我不断看到如何扩展数组的不同语法。这是我看到的两个。有人能解释一下有什么区别吗?

extension Array where Element == StringProtocol {
    func foo(){}
}

extension Array where Element:StringProtocol {
    func foo(){}
}
Run Code Online (Sandbox Code Playgroud)

那么有什么区别呢?

奖金:

我正在尝试编写一个[String]与 和一起使用的扩展[Substring],并且建议我将其基于StringProtocol,因此如上所述。但是,如果我尝试做如下的事情......

func foo(separator:Character)

    for line in self{

        let components = line.split(separator: separator, maxSplits: 1, omittingEmptySubsequences: false)

        let prefix = components[0].replacingOccurrences(of: "\\s+$", with: "", options: .regularExpression) // Only trim the end of the prefix
        let suffix = components.count > 1
            ? components[1].trimmingCharacters(in: .whitespaces) // Perform full trim on the suffix
            : nil
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

我明白了...

成员“split”不能用于协议类型“StringProtocol”的值;使用通用约束代替

那么你怎么说Element是一个TwhereT符合 呢StringProtocol

Mar*_*n R 5

简短回答:在这个特定的用例中,

\n\n
extension Array where Element: StringProtocol {}\n
Run Code Online (Sandbox Code Playgroud)\n\n

就是你想要的。它定义了符合Twhere的数组的扩展。另一方面,TStringProtocol

\n\n
extension Array where Element == StringProtocol {}\n
Run Code Online (Sandbox Code Playgroud)\n\n

定义了\n\xe2\x80\x93类型数组的扩展[StringProtocol],据我所知\xe2\x80\x93\xc2\xa0不可能创建,因为该协议\n有关联的类型要求。

\n\n
\n\n

长答案:让我们为一个没有关联类型的简单协议执行此操作:

\n\n
protocol MyProtocol {\n    var id: Int { get }\n}\n\nextension Array where Element: MyProtocol {\n    func foo() {\n        for elem in self { print(elem.id) }\n    }\n}\n\nextension Array where Element == MyProtocol {\n    func bar() {\n        for elem in self { print(elem.id) }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

以及符合协议的两种类型

\n\n
struct A: MyProtocol {\n    let id: Int\n}\nstruct B: MyProtocol {\n    let id: Int\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我可以调用\nfoo()类型[A]和类型的数组[B],因为 和 AB符合MyProtocol

\n\n
let aArray = [A(id: 1), A(id: 2), A(id: 3)]\nlet bArray = [B(id: 4), B(id: 5), B(id: 6)]\n\naArray.foo()\nbArray.foo()\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一方面,bar()可以在 \n 类型的数组上调用[MyProtocol],该数组是 \xe2\x80\x9cboxes\xe2\x80\x9d 的数组,其中每个框可以\n保存符合该协议的类型的任何值:

\n\n
let pArray: [MyProtocol] = [A(id: 10), B(id: 11)]\npArray.bar()\n
Run Code Online (Sandbox Code Playgroud)\n\n

(有关更多信息,请参阅在 Swift 中使用协议时的类型转换。)但这不会编译

\n\n
aArray.bar() // \'[A]\' is not convertible to \'Array<MyProtocol>\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

除非数组显式转换为类型数组[MyProtocol]

\n\n
(aArray as [MyProtocol]).bar()\n
Run Code Online (Sandbox Code Playgroud)\n\n

它创建一个新数组并且是一个O(N)操作,如上面提到的答案中所述。反之亦然,

\n\n
pArray.foo() // Using \'MyProtocol\' as a concrete type conforming to protocol \'MyProtocol\' is not supported\n
Run Code Online (Sandbox Code Playgroud)\n\n

无法编译,因为协议不符合其自身

\n