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

29 ios swift equatable

我已经看到了这个Swift Equatable Protocol问题的答案,该问题提到了如何==在全局范围内声明该方法.

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

// extension Foo: Equatable {}

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

struct Foo {
    let bar:Int
}
Run Code Online (Sandbox Code Playgroud)

它的实现需要在全球范围内声明的事实使得它似乎是偶然的,并且协议不同,即使Equatable被采用.

Equatable协议如何只是语法糖只是让(我们和)编译器安全地知道我们的类型实现了协议所需的方法?

为什么运算符实现必须全局声明,即使对于协议也是如此?这是由于调度操作员的某种不同方式吗?

rob*_*off 22

UPDATE

来自Xcode 8 beta 4发行说明:

可以在其类型或扩展中定义操作符.例如:

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

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

protocol Equatable {
    static func ==(lhs: Self, rhs: Self) -> Bool
}
Run Code Online (Sandbox Code Playgroud)

原版的

这是最近在swift-evolution列表中讨论的(2016-01-31至2016-02-09).这是Chris Lattner所说的关于在结构或类范围内声明运算符的内容:

是的,这是一个通常需要的特征(至少对称运算符).在类声明中动态调度运算符也很有用.我不认为我们有一个坚定的建议,即确定名称查找的工作方式.

后来(回复Haravikk):

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

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

就个人而言,我只是坚持我们现在所拥有的,即 - 将特定类/结构中的运算符实现视为全局定义,如果同一个签名被多次声明则抛出错误.

我们需要多个模块来定义运营商的实例,我们需要运营商扩展,我们需要追溯一致性,就像任何其他成员一样.


vad*_*ian 7

从说明文档

运算符函数被定义为具有函数名称的全局函数,该函数名称与要重载的运算符匹配.

该函数是全局定义的,而不是作为目标类或结构的方法,因此它可以用作目标类或结构的现有实例之间的中缀运算符.

我用Vector2D通用表达式目标类或结构替换了引号中的具体结构()的名称


Rob*_*ier 7

它的实现需要在全球范围内声明的事实使得它似乎是偶然的和不同于协议,即使采用Equatable也是如此.

无论是需要全局函数,类方法还是实例方法,每个协议都是如此.您始终可以独立于是否存在需要它的协议来实现.

Equatable协议如何只是语法糖只是让(我们和)编译器安全地知道我们的类型实现了协议所需的方法?

那不是糖.这是协议的定义和协议的整个要点.它告诉你这种类型可以应用这些东西.

为什么运算符实现必须全局声明,即使对于协议也是如此?这是由于调度操作员的某种不同方式吗?

因为那是Swift的语法.运算符函数实现必须是全局函数.Swift团队一直有兴趣改变它以使其更加一致,但今天这就是Swift的工作原理.