Swift协议强制使用Equatable协议

4

我定义了两个协议。 第一个协议(NameProtocol)需要执行Equatable协议。 而另一个类(BuilderProtocol)有一个返回第一个协议(NameProtocol)的方法。

public protocol NameProtocol : Equatable {
    var name: String { get }
}

public protocol BuilderProtocol {
    func build() -> NameProtocol? // Compiler error
    init()
}

编译器错误: “协议 'NameProtocol' 只能用作泛型约束,因为它具有 Self 或关联类型的要求”

我需要通过 build() 返回符合 NameProtocol 的对象,并且可以在该对象上定义 == 。

有什么方法可以让这个实现起来吗?

谢谢。


如果在 BuilderProtocol 中使用 typealias ,如何使数组声明工作?

public protocol OtherRelatedProtocol {
    var allNames : Array<NameProtocol> { get }
}

结论

我将移除Equatable并实现一个isEqual方法。

public protocol NameProtocol {
    func isEqual(nameable: NameProtocol) -> Bool
    var name: String { get }
}

那个错误信息有误导性(仍在3.0.2中)。它应该是“if它有”。 - Raphael
1个回答

3
如果你熟悉Java或C#,那么Swift协议介于泛型和接口之间。例如,在协议中,你可以做如下操作:
protocol Foo {
    func compareWith(foo: Self)
}

实现这个协议的类将拥有一个名为compareWith的方法,它接受一个属于自身类型的对象作为参数(而不是Foo类型的对象)。
这就是编译器所谓的“Self或关联类型要求”,以及Equatable的定义方式(它需要一个接受两个Self操作数的operator==)。但这些协议的缺点是,你只能将它们用作泛型约束:你不能将它们用作表达式类型。
解决方案是使用泛型。在这种情况下,您可以使您的ProtocolBuilder协议成为泛型协议,并加上一个实现NameProtocol的类型约束。
public protocol NameProtocol : Equatable {
    var name: String { get }
}

public protocol BuilderProtocol {
    typealias T: NameProtocol
    func build() -> T?
    init()
}

是的,马特,我应该进行测试的。 - zneak
特别是如果你只是要重复我在评论中已经说过的话。 :) - matt
不好意思,是我数错了,需要去睡觉了。你先到达那里了。 - zneak
谢谢,选项2给我留下了另一个问题,我将更新问题以展示它。 - Vincent Bernier
@zneak 我的目标是拥有一个能够分发对象的框架,但我希望外部世界只知道协议,因为确切的类可能会改变,或者在这种情况下,协议可以由结构体支持。但我的目标是将实现细节保留在框架内部,并尽可能获得最大的灵活性。 - Vincent Bernier
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接