扩展协议与直接调用协议之间的区别

时间:2018-11-18 21:25:05

标签: swift protocols

我得到了以下代码:

protocol Protocol {
    var id: Int { get }
}

extension Array where Element: Protocol {
    func contains(_protocol: Protocol) -> Bool {
        return contains(where: { $0.id == _protocol.id })
    }
}

class Class {
    func method<T: Protocol>(_protocol: T) {
        var arr = [Protocol]()

        // Does compile
        let contains = arr.contains(where: { $0.id == _protocol.id })

        // Doens't compile
        arr.contains(_protocol: _protocol)
    }
}

为什么我注释“不编译”的代码行不能编译?这是错误:

Incorrect argument label in call (have '_protocol:', expected 'where:')

当我将扩展名中的方法名称更改为其他名称时,例如containz(当然,将调用它的方法名称更改为containz),当我尝试执行以下操作时会出现此错误称呼它:

Using 'Protocol' as a concrete type conforming to protocol 'Protocol' is not supported

但是,当我尝试通过扩展调用它时,为什么它不起作用,但是当我直接在扩展中创建函数时,它却起作用了?我看不出有什么区别。

1 个答案:

答案 0 :(得分:1)

我同意马特的观点,即基本答案是Protocol doesn't conform to itself?,但无论如何还是值得回答的,因为在这种情况下,答案非常简单。首先,阅读有关以下问题的链接问题:[Protocol]为什么不能以您认为的方式工作(特别是Hamish的答案,它比我编写的公认答案要广泛得多)。 [Protocol]where Element: Protocol子句不匹配,因为Protocol不是符合Protocol的具体类型(因为它不是具体类型)。

但是您在这里不需要[Protocol]。您拥有T: Protocol,因此您可以(并且应该)使用它:

var arr = [T]()

进行了此更改后,其余的内容应会按预期工作,因为T是符合协议的具体类型。