协议操作符为什么必须作为全局函数来实现?
我已经看到了这个Swift Equatable Protocol问题的答案,它提到了如何在全局范围内声明==
方法。
如果我不采用Equatable
,我仍然可以声明==
来testing我的两个types之间的平等。
// extension Foo: Equatable {} func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs.bar == rhs.bar } struct Foo { let bar:Int }
其实施需要在全球范围内进行宣布的事实,使得它似乎与议定书是偶然的 ,并且与议定书有所不同 ,即使通过了“ Equatable
。
Equatable
协议如何超过语法糖,仅仅让我们和编译器安全地知道我们的types实现了协议所需要的方法?
为什么运营商的实施必须在全球范围内宣布,即使对于协议? 这是否由于运营商派遣的不同方式?
UPDATE
从Xcode 8 beta 4发行说明:
运营商可以在其types或扩展中定义。 例如:
struct Foo: Equatable { let value: Int static func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs.value == rhs.value } }
这些操作符必须被声明为
static
(或者在一个类,class final
一个class final
),并且和全局对象具有相同的签名。 作为这种改变的一部分,协议中声明的操作符要求也必须明确声明为static
:protocol Equatable { static func ==(lhs: Self, rhs: Self) -> Bool }
原版的
近期(2016-01-31至2016-02-09)在快速发展名单上进行了讨论。 Chris Lattner说:关于在结构体或类的作用域中声明运算符:
是的,这是一个普遍需要的function(至less对于对称运算符)。 在类声明中dynamic调度运算符也是很好的。 我不认为我们有一个坚定的build议,确定名称查找是如何工作的。
后来(回复Haravikk):
什么是名字查询问题? 你的意思是Foo == Foo的运算符存在于多个位置吗?
是。 名称查找必须有一个明确的search顺序,它定义了阴影和无效的多个定义规则。
就个人而言,我只是坚持我们现在所拥有的东西,即 – 将特定类/结构中的运算符实现视为全局定义,并且如果同一个签名被声明了多次,则会抛出错误。
我们需要多个模块来定义运营商的实例,我们需要运营商在扩展,我们需要追溯符合工作,如任何其他成员。
来自文档的说明
运算符函数被定义为一个全局函数,其函数名称与要重载的运算符相匹配。
该函数是全局定义的,而不是作为目标类或结构的方法,因此它可以在目标类或结构的现有实例之间用作中缀运算符。
我用通用expression式目标类或结构在引用中replace了具体结构( Vector2D
)的名称
其实施需要在全球范围内进行宣布的事实,使得它似乎与议定书是偶然的,并且与议定书有所不同,即使通过了“可接受的等值”。
无论是需要全局函数,类方法还是实例方法,每个协议都是如此。 你总是可以执行一些事情,而不pipe是否有一个协议需要它。
Equatable协议如何超过语法糖,仅仅让我们和编译器安全地知道我们的types实现了协议所需要的方法?
这不是糖。 这是协议的定义和协议的全部要点。 它告诉你,这种types可以应用这些东西。
为什么运营商的实施必须在全球范围内宣布,即使对于协议? 这是否由于运营商派遣的不同方式?
因为这是Swift语法。 运算符函数实现必须是全局函数。 Swift团队有兴趣改变这一点,使其更加一致,但是今天这就是Swift的工作原理。
在Swift标准库中,定义了“==”运算符。 它不具有关联的一方或另一方的比较,并且在整个Swift操作符顺序中具有编号的优先顺序。 你可以检查这个,如果你CMD点击Swift上的“导入Swift”
infix operator == { associativity none precedence 130 }
对于Int's,图书馆已经将Int / Int8 / Int16 / Int32 / Int64设置为Equatable:
public func ==(lhs: Int, rhs: Int) -> Bool
就像许多其他types一样。
Int在一个扩展中做成了Hashable(在那里符合该协议,你需要创build一个var hashValue:Int {get},它对应用程序的每次执行都会改变:
extension Int : Hashable { public var hashValue: Int { get } }
一般来说,运算符'=='和协议需要在struct / enum / class之外的顶层进行声明,因为你正在扩展语言,现在,这就是swift编译的方式。 所有Swift的运算符都是在全局范围内定义的属性。
对于你的“Foo”,你通过添加func来采用Equatable:
func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs.bar == rhs.bar }
在协议中使用“Self”本地variables:
public protocol Equatable { public func ==(lhs: Self, rhs: Self) -> Bool }