为什么以下协议具有此必需功能?

时间:2015-06-25 00:02:23

标签: swift protocols

在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
  } 
}

我对整个协议扩展的事情有点困惑。为什么他们在isEqualTo(other: Drawable) -> Bool协议中有Drawable,然后只在self等于时延伸?为什么isEqualTo必须成为所有Drawable对象的必需方法?从我的角度来看,如果一个新的类/结构没有实现Equatable,那么这些对象就无法在逻辑上检查其是否相等,所以它们不能<\ n < / em>实现一个等同的方法。我认为将它作为可选实现更有意义。我逻辑中的错误在哪里?

2 个答案:

答案 0 :(得分:3)

正在解决的问题是泛型的限制。

让我们说我们有一个Bird结构和Insect结构。通用equable允许我们定义b1,其中实际的对象类型是相同的类型。所以我们可以让Bird采用Equatable,这样如果我们将b2i1都输入Bird,我们可以决定它们是否相等。我们可以让Insect采用Equatable,这样如果我们将i2==都输入为Insect,我们就可以决定它们是否相等。

但现在假设Bird和Insect都采用Flier协议。你不能让Flier采用Equatable,因为泛型的工作方式有限制。因此,如果将两个对象键入为Flier,则无法实现它们的兼容性。

该视频演示了协议扩展解决了这个问题。通过Flier上的协议扩展,您可以定义一个不同的方法,该方法比较两个Fliers并确定它们是否相等 - 即,首先确定它们是否属于同一个类然后应用{{1} }。因此,您可以理解Flier(协议)的等同性。

答案 1 :(得分:1)

我只能猜测为什么isEqualTo:是drawable协议的必需方法。也许是这样,无论是什么吸引这些东西,都不会浪费时间画两次相同的东西?

然而,我可以评论其余部分。

Equatable是一个Swift协议(在Objective-C中不可用),它要求为该类型定义==运算符。

在Objective-C中,没有运算符重载。此外,在Objective-C中,使用==比较对象只是比较它们的指针。如果对象是同一个对象(相同的内存位置),==将返回true。如果我们想要查看对象是否是不同的对象但仍然被认为是相等的,我们必须使用isEqualTo:。这是由NSObject定义的方法,默认实现只返回==比较的结果。但是类往往会覆盖它。

在Swift中,==有不同的行为。在Swift中,==返回的行为与我们期望isEqualTo:方法在Objective-C中的行为方式类似。那是因为Swift有===运算符用于比较引用。如果这些对象相同(相同的内存位置),则===返回true,但==是一个自定义实现的方法,用于确定对象是否被认为是相等的,即使它们在不同的记忆位置。

所以我猜测Drawable协议在声明isEqualTo:作为其必需方法之一时,会考虑Objective-C类。

我们也可以这样编写Drawable协议:

protocol Drawable: Equatable {
    func draw()
}

从严格的Swift角度来看,这是一个大致相当的协议定义。但这意味着使用Drawable对象的任何人都希望将它们与Swift中的==进行比较,而不是isEqualTo:。而且,这意味着如果我们想在协议中使用任何Objective-C定义的对象,现在我们必须为每个对象实现一个自定义==函数,这很可能是这样的:

func == (left ObjCClass, right ObjCClass) -> Bool {
    return left.isEqualTo(right)
}

但我们必须为我们想要定义为Drawable的每个 Objective-C类执行此操作。

另一种方法是使用isEqualTo:(一种非常常见的Objective-C方法)定义我们提供的协议。

现在,为了使我们的所有Swift类型都符合Drawable,我们所要做的就是实现draw()方法并符合Equatable。只要我们符合Equatable,扩展程序就会将isEqualTo:方法作为简单的return left == right有效地添加到我们的Swift类型中(并且==方法的存在就是什么Equatable协议保证)。