为什么下面的协议有这个必需的功能?
Why does the following protocol have this required function?
WWDC 2015 中提到了以下代码:
protocol Drawable {
func isEqualTo(other: Drawable) -> Bool
func draw()
}
extension Drawable where Self : Equatable {
func isEqualTo(other: Drawable) -> Bool {
if let o = other as? Self { return self == o }
return false
}
}
我对整个协议扩展的事情有点困惑。为什么他们会在 Drawable
协议中包含 isEqualTo(other: Drawable) -> Bool
,然后仅在 self
可等式时才扩展?为什么 isEqualTo
应该是所有 Drawable 对象的必需方法?在我看来,如果一个新的 class/struct 还没有实现 Equatable
,那么这些对象就没有能力进行逻辑上的相等性检查,所以它们 不能 [=21] =] 实施一个平等的方法。我认为将其作为可选实现会更有意义。我的逻辑错在哪里?
我只能猜测为什么 isEqualTo:
是可绘制协议的必需方法。也许这样不管画这些东西的人都不会浪费时间画同样的东西两次?
不过我可以评论其余部分。
Equatable
是一个 Swift 协议(在 Objective-C 中不可用),它要求为该类型定义一个 ==
运算符。
在Objective-C中,没有运算符重载。而且,在Objective-C中,使用==
来比较对象只是比较它们的指针。如果对象是相同的对象(相同的内存位置),则 ==
returns 为真。如果我们想查看对象是否是不同的对象但仍然被认为是相等的,我们必须使用 isEqualTo:
。这是由 NSObject
定义的方法,默认实现只是 returns ==
比较的结果。但是 classes 倾向于覆盖它。
在 Swift 中,==
有不同的行为。在 Swift 中,==
returns 的行为与我们期望 isEqualTo:
方法在 Objective-C 中的行为相似。这是因为 Swift 具有用于比较引用的 ===
运算符。 ===
returns 如果这些对象 相同 (相同的内存位置),则为真,但 ==
是自定义实现的方法,用于确定对象是否即使它们位于不同的内存位置,也被视为相等。
所以我猜 Drawable
协议在将 isEqualTo:
声明为其必需方法之一时考虑到了 Objective-C classes。
我们也可以这样编写 Drawable
协议:
protocol Drawable: Equatable {
func draw()
}
从严格的 Swift 角度来看,这是一个大致等效的协议定义。但这意味着使用 Drawable
对象的任何人都希望将它们与 Swift 中的 ==
而不是 isEqualTo:
进行比较。而且,这意味着如果我们想使用协议中的任何 Objective-C 定义的对象,现在我们必须为每个对象实现一个自定义的 ==
函数,这很可能如下所示:
func == (left ObjCClass, right ObjCClass) -> Bool {
return left.isEqualTo(right)
}
但是我们必须为每个 Objective-C class 做这个我们想定义为Drawable
.
另一种方法是使用 isEqualTo:
一种非常常见的 Objective-C 方法,按照您介绍的方式定义我们的协议。
现在,要使我们所有的 Swift 类型都符合 Drawable
,我们所要做的就是实现 draw()
方法并符合 Equatable
。只要我们符合 Equatable
,扩展就会将 isEqualTo:
方法作为简单的 return left == right
有效地添加到我们的 Swift 类型中(并且存在 ==
方法是 Equatable
协议保证的。
正在解决的问题是泛型的限制。
假设我们有一个 Bird 结构体和一个 Insect 结构体。通用等值表让我们定义 ==
,其中实际对象类型是相同的类型。所以我们可以让 Bird 采用 Equatable 这样如果我们有 b1
和 b2
都键入为 Bird 我们可以判断它们是否相等。我们可以让 Insect 采用 Equatable,这样如果我们 i1
和 i2
都输入为 Insect,我们就可以判断它们是否相等。
但是现在假设Bird和Insect都采用了Flier协议。您不能 让 Flier 采用 Equatable,因为泛型的工作方式存在限制。因此,如果两个对象的类型都为 Flier,则无法为它们实现等同性。
该视频演示了协议扩展解决了这个问题。使用 Flier 上的协议扩展,您可以定义一个 different 方法来比较两个 Fliers 并确定它们是否相等 - 即首先确定它们是否相同 class然后应用 ==
。因此,您可以理解 Flier(一种协议)的等同性。
WWDC 2015 中提到了以下代码:
protocol Drawable {
func isEqualTo(other: Drawable) -> Bool
func draw()
}
extension Drawable where Self : Equatable {
func isEqualTo(other: Drawable) -> Bool {
if let o = other as? Self { return self == o }
return false
}
}
我对整个协议扩展的事情有点困惑。为什么他们会在 Drawable
协议中包含 isEqualTo(other: Drawable) -> Bool
,然后仅在 self
可等式时才扩展?为什么 isEqualTo
应该是所有 Drawable 对象的必需方法?在我看来,如果一个新的 class/struct 还没有实现 Equatable
,那么这些对象就没有能力进行逻辑上的相等性检查,所以它们 不能 [=21] =] 实施一个平等的方法。我认为将其作为可选实现会更有意义。我的逻辑错在哪里?
我只能猜测为什么 isEqualTo:
是可绘制协议的必需方法。也许这样不管画这些东西的人都不会浪费时间画同样的东西两次?
不过我可以评论其余部分。
Equatable
是一个 Swift 协议(在 Objective-C 中不可用),它要求为该类型定义一个 ==
运算符。
在Objective-C中,没有运算符重载。而且,在Objective-C中,使用==
来比较对象只是比较它们的指针。如果对象是相同的对象(相同的内存位置),则 ==
returns 为真。如果我们想查看对象是否是不同的对象但仍然被认为是相等的,我们必须使用 isEqualTo:
。这是由 NSObject
定义的方法,默认实现只是 returns ==
比较的结果。但是 classes 倾向于覆盖它。
在 Swift 中,==
有不同的行为。在 Swift 中,==
returns 的行为与我们期望 isEqualTo:
方法在 Objective-C 中的行为相似。这是因为 Swift 具有用于比较引用的 ===
运算符。 ===
returns 如果这些对象 相同 (相同的内存位置),则为真,但 ==
是自定义实现的方法,用于确定对象是否即使它们位于不同的内存位置,也被视为相等。
所以我猜 Drawable
协议在将 isEqualTo:
声明为其必需方法之一时考虑到了 Objective-C classes。
我们也可以这样编写 Drawable
协议:
protocol Drawable: Equatable {
func draw()
}
从严格的 Swift 角度来看,这是一个大致等效的协议定义。但这意味着使用 Drawable
对象的任何人都希望将它们与 Swift 中的 ==
而不是 isEqualTo:
进行比较。而且,这意味着如果我们想使用协议中的任何 Objective-C 定义的对象,现在我们必须为每个对象实现一个自定义的 ==
函数,这很可能如下所示:
func == (left ObjCClass, right ObjCClass) -> Bool {
return left.isEqualTo(right)
}
但是我们必须为每个 Objective-C class 做这个我们想定义为Drawable
.
另一种方法是使用 isEqualTo:
一种非常常见的 Objective-C 方法,按照您介绍的方式定义我们的协议。
现在,要使我们所有的 Swift 类型都符合 Drawable
,我们所要做的就是实现 draw()
方法并符合 Equatable
。只要我们符合 Equatable
,扩展就会将 isEqualTo:
方法作为简单的 return left == right
有效地添加到我们的 Swift 类型中(并且存在 ==
方法是 Equatable
协议保证的。
正在解决的问题是泛型的限制。
假设我们有一个 Bird 结构体和一个 Insect 结构体。通用等值表让我们定义 ==
,其中实际对象类型是相同的类型。所以我们可以让 Bird 采用 Equatable 这样如果我们有 b1
和 b2
都键入为 Bird 我们可以判断它们是否相等。我们可以让 Insect 采用 Equatable,这样如果我们 i1
和 i2
都输入为 Insect,我们就可以判断它们是否相等。
但是现在假设Bird和Insect都采用了Flier协议。您不能 让 Flier 采用 Equatable,因为泛型的工作方式存在限制。因此,如果两个对象的类型都为 Flier,则无法为它们实现等同性。
该视频演示了协议扩展解决了这个问题。使用 Flier 上的协议扩展,您可以定义一个 different 方法来比较两个 Fliers 并确定它们是否相等 - 即首先确定它们是否相同 class然后应用 ==
。因此,您可以理解 Flier(一种协议)的等同性。