一尘不染

为什么必须将协议运算符实现为全局功能?

swift

我已经看到了这个“快速平等协议”问题的答案,该问题提到了如何==在全局范围内声明该方法。

如果我不采用Equatable,我仍然可以声明==测试两种类型之间的相等性。

// extension Foo: Equatable {}

func ==(lhs: Foo, rhs: Foo) -> Bool {
    return lhs.bar == rhs.bar
}

struct Foo {
    let bar:Int
}

需要在全局范围内声明其实现这一事实,这使得该协议似乎是 附带的 ,也与协议 有所不同 ,即使Equatable已被采纳。

Equatable协议除了仅使(我们和)编译器安全地知道我们的类型实现了协议所需方法的语法糖外,还有什么?

为什么即使对于协议,也必须全局声明操作员实现?这是否是由于调度操作员的方式不同?


阅读 238

收藏
2020-07-07

共1个答案

一尘不染

更新

从Xcode 8 beta 4发行说明中:

可以在类型或扩展名内定义运算符。例如:

struct Foo: Equatable {
    let value: Int
    static func ==(lhs: Foo, rhs: Foo) -> Bool {
        return lhs.value == rhs.value
    }
}

此类运算符必须声明为static(或在一个类中class final),并且必须具有与全局对应运算符相同的签名。作为此更改的一部分,还必须明确声明协议中声明的操作员要求static

protocol Equatable {
    static func ==(lhs: Self, rhs: Self) -> Bool
}

原版的

最近(2016-01-31至2016-02-09)在swift-evolution列表上对此进行了讨论。克里斯·拉特纳(ChrisLattner)所说的关于在结构或类范围内声明运算符的内容:

是的,这是一个普遍希望的功能(至少对于对称算子而言)。这对于在类声明中动态分配运算符也非常有用。我认为我们没有一个明确的建议来确定名称查找与此相关的工作方式。

后来(回复Haravikk):

名称查找问题是什么?您是说Foo == Foo的运算符存在于多个位置的情况吗?

是。名称查找必须具有定义明确的搜索顺序,该顺序定义阴影和无效的多个定义规则。

就我个人而言,我只是坚持我们现在拥有的东西,即,无论如何都将特定类/结构中的运算符实现视为全局定义,并且如果多次声明同一签名,则会抛出错误。

我们需要多个模块来定义一个运算符的实例,我们需要扩展中的运算符,并且需要追溯一致性才能像其他任何成员一样工作。

2020-07-07