swift - Element == StringProtocol 和 Element : StringProtocol? 之间有什么区别

标签 swift swift4 swift-extensions

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

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

那么你怎么说Element是一个T,其中T符合StringProtocol

最佳答案

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

extension Array where Element: StringProtocol {}

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

extension Array where Element == StringProtocol {}

定义了[StringProtocol]类型数组的扩展,它是 – 据我所知 – 不可能创建,因为该协议(protocol) 有相关的类型要求。


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

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) }
    }
}

以及符合协议(protocol)的两种类型

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],这是一个“盒子”数组,其中每个盒子可以 保存符合该协议(protocol)的类型的任何值:

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

(有关更多信息,请参阅 Type conversion when using protocol in Swift 关于这一点。)但这不能编译

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

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

(aArray as [MyProtocol]).bar()

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

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

无法编译,因为 a protocol does not conform to itself .

关于swift - Element == StringProtocol 和 Element : StringProtocol? 之间有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49206354/

相关文章:

ios - 选中时的 Tabman Image Tint 颜色

ios - UITableView 单元格自动布局约束

swift - 打开和保存在非常简单的基于文档的 Swift 4 应用程序中不起作用

ios - 将 UITableViewCell 放在 sibling 下面

ios - 无法在 Testflight 的(Internal Tester)中开始测试

具有泛型类型的 Swift 协议(protocol)

arrays - Xcode 10.2 中下标的使用不明确

swift - 如何解决协议(protocol)和类字段类型之间的冲突?

json - 快速解析来自 POST 请求的数据

swift - NSGridview 的背景色