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?
简短回答:在这个特定的用例中,
\n\nextension Array where Element: StringProtocol {}\nRun Code Online (Sandbox Code Playgroud)\n\n就是你想要的。它定义了符合Twhere的数组的扩展。另一方面,TStringProtocol
extension Array where Element == StringProtocol {}\nRun Code Online (Sandbox Code Playgroud)\n\n定义了\n\xe2\x80\x93类型数组的扩展[StringProtocol],据我所知\xe2\x80\x93\xc2\xa0不可能创建,因为该协议\n有关联的类型要求。
长答案:让我们为一个没有关联类型的简单协议执行此操作:
\n\nprotocol 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}\nRun Code Online (Sandbox Code Playgroud)\n\n以及符合协议的两种类型
\n\nstruct A: MyProtocol {\n let id: Int\n}\nstruct B: MyProtocol {\n let id: Int\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后我可以调用\nfoo()类型[A]和类型的数组[B],因为 和 A都B符合MyProtocol:
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()\nRun Code Online (Sandbox Code Playgroud)\n\n另一方面,bar()可以在 \n 类型的数组上调用[MyProtocol],该数组是 \xe2\x80\x9cboxes\xe2\x80\x9d 的数组,其中每个框可以\n保存符合该协议的类型的任何值:
let pArray: [MyProtocol] = [A(id: 10), B(id: 11)]\npArray.bar()\nRun Code Online (Sandbox Code Playgroud)\n\n(有关更多信息,请参阅在 Swift 中使用协议时的类型转换。)但这不会编译
\n\naArray.bar() // \'[A]\' is not convertible to \'Array<MyProtocol>\'\nRun Code Online (Sandbox Code Playgroud)\n\n除非数组显式转换为类型数组[MyProtocol]:
(aArray as [MyProtocol]).bar()\nRun Code Online (Sandbox Code Playgroud)\n\n它创建一个新数组并且是一个O(N)操作,如上面提到的答案中所述。反之亦然,
pArray.foo() // Using \'MyProtocol\' as a concrete type conforming to protocol \'MyProtocol\' is not supported\nRun Code Online (Sandbox Code Playgroud)\n\n无法编译,因为协议不符合其自身。
\n