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

What's the difference between Element == StringProtocol and Element: StringProtocol?

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

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

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

那有什么区别呢?

奖金:

我正在尝试编写一个与 [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
        ...
    }

}

我明白了...

Member 'split' cannot be used on value of protocol type 'StringProtocol'; use a generic constraint instead

那么你怎么说 ElementT 其中 T 符合 StringProtocol

简答: 在这个特定的 use-case,

extension Array where Element: StringProtocol {}

就是你想要的。它定义了 T 数组的扩展,其中 T 符合 StringProtocol。另一方面,

extension Array where Element == StringProtocol {}

定义 [StringProtocol] 类型数组的扩展 – 据我所知 – 不可能创建,因为该协议 具有关联的类型要求。


长答案:让我们为一个简单的协议做这个,它有 没有关联类型:

protocol MyProtocol {
    var id: Int { get }
}

extension Array where Element: MyProtocol {
    func foo() {
        for elem in self { print(elem.id) }
    }
}

extension Array where Element == MyProtocol {
    func bar() {
        for elem in self { print(elem.id) }
    }
}

和两种符合协议的类型

struct A: MyProtocol {
    let id: Int
}
struct B: MyProtocol {
    let id: Int
}

然后我可以在 [A] 类型和 [B] 类型的数组上调用 foo() 因为 AB 都符合 MyProtocol:

let aArray = [A(id: 1), A(id: 2), A(id: 3)]
let bArray = [B(id: 4), B(id: 5), B(id: 6)]

aArray.foo()
bArray.foo()

另一方面,bar()可以在类型数组上调用 [MyProtocol],这是一个“盒子”数组,其中每个盒子可以 持有符合该协议的类型的任何值:

let pArray: [MyProtocol] = [A(id: 10), B(id: 11)]
pArray.bar()

(有关详细信息,请参阅 关于那个。)但这不会编译

aArray.bar() // '[A]' is not convertible to 'Array<MyProtocol>'

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

(aArray as [MyProtocol]).bar()

创建一个新数组并且是一个 O(N) 操作,如中所述 above-mentioned 回答。反之亦然,

pArray.foo() // Using 'MyProtocol' as a concrete type conforming to protocol 'MyProtocol' is not supported

无法编译,因为 .