Arrays 如何在Swift中比较两个协议数组的相等性?
我遇到了一种情况,我相信这种情况并不罕见。我有两个符合协议的对象数组,我想检查它们是否相等 我真正想做的是:Arrays 如何在Swift中比较两个协议数组的相等性?,arrays,swift,protocols,swift2,heterogeneous,Arrays,Swift,Protocols,Swift2,Heterogeneous,我遇到了一种情况,我相信这种情况并不罕见。我有两个符合协议的对象数组,我想检查它们是否相等 我真正想做的是: protocol Pattern: Equatable { func isEqualTo(other: Pattern) -> Bool } func ==(rhs:Pattern, lhs:Pattern) -> Bool { return rhs.isEqualTo(lhs) } extension Equatable where Self : Pat
protocol Pattern: Equatable
{
func isEqualTo(other: Pattern) -> Bool
}
func ==(rhs:Pattern, lhs:Pattern) -> Bool
{
return rhs.isEqualTo(lhs)
}
extension Equatable where Self : Pattern
{
func isEqualTo(other: Pattern) -> Bool
{
guard let o = other as? Self else { return false }
return self == o
}
}
但是,这会导致编译错误:
错误:(10,30)协议“模式”只能用作一般约束,因为它具有自身或关联的类型要求
基于此,我意识到我需要丢失协议上的可平衡继承,并将其推到具体的“模式”声明上。虽然我真的不明白为什么。如果我通过重载==来定义两个对象如何基于协议相等,那么就我所见,实际上没有问题。我甚至不需要知道实际的类型,也不需要知道它们是类还是结构
无论如何,这一切都很好,我现在可以比较concretePattern.isEqualTo(otherConcretePattern)
,但问题是我不能再比较这些对象的数组,就像我可以比较一个具体类型的数组一样,因为数组相等依赖于重载==运算符
到目前为止,我能做的最好的事情就是通过扩展将isEqualTo
方法glom到CollectionType
上。这至少允许我比较数组。但坦率地说,这个代码很糟糕
extension CollectionType where Generator.Element == Pattern
{
func isEqualTo(patterns:[Pattern]) -> Bool {
return self.count as? Int == patterns.count && !zip(self, patterns).contains { !$0.isEqualTo($1) }
}
}
真的没有别的办法吗?请告诉我我遗漏了一些明显的东西。快速回答:
protocol _Pattern
{
func _isEqualTo(_other: Any) -> Bool?
}
extension _Pattern where Self: Pattern
{
func _isEqualTo(_other: Any) -> Bool?
{
return (_other as? Self).map({ self.isEqualTo($0) })
}
}
protocol Pattern: _Pattern, Equatable
{
func isEqualTo(other: Self) -> Bool
}
extension Pattern
{
func isEqualTo(other: _Pattern) -> Bool
{
return _isEqualTo(other) ?? false
}
}
func == <T: Pattern>(rhs: T, lhs: T) -> Bool
{
return rhs.isEqualTo(lhs)
}
protocol\u模式
{
func(其他:有)>Bool??
}
扩展模式,其中Self:Pattern
{
func(其他:有)>Bool??
{
return(_otheras?Self).map({Self.isEqualTo($0)})
}
}
协议模式:_模式,可均衡
{
func isEqualTo(其他:自身)->Bool
}
扩展模式
{
func isEqualTo(其他:_模式)->Bool
{
返回“isEqualTo(其他)”?错误
}
}
func==(rhs:T,lhs:T)->Bool
{
返回右侧isEqualTo(左侧)
}
这是我自己开发的一种模式(双关语),在这种情况下效果非常好\u模式
是一种自动实现的协议,由新的协议扩展功能提供,表示模式的类型擦除版本
我有两个符合协议的对象数组,我想检查它们是否相等
所以,如果两个数组中的所有元素都相等,并且所有元素都符合模式,那么可以说这两个数组是相等的。i、 e
若a,b,c和d都是符合模式的东西,你们想要
a == c
a != b
a != d
b != d
let array1: [Pattern] = [a, b, c]
let array2: [Pattern] = [a, b, a]
let array3: [Pattern] = [a, d, c]
array1 == array2 // true
array1 == array3 // false
最简单的方法是为两个模式数组定义一个相等运算符,即
protocol Pattern
{
func isEqualTo(other: Pattern) -> Bool
}
func ==(rhs: Pattern, lhs: Pattern) -> Bool
{
return rhs.isEqualTo(lhs)
}
func ==(lhs: [Pattern], rhs: [Pattern]) -> Bool
{
guard lhs.count == rhs.count else { return false }
var i1 = lhs.generate()
var i2 = rhs.generate()
var isEqual = true
while let e1 = i1.next(), e2 = i2.next() where isEqual
{
isEqual = e1 == e2
}
return isEqual
}
我定义了两种符合模式的类型,并尝试了各种等式比较,结果都很有效
struct Foo: Pattern
{
let data: String
init(data: String)
{
self.data = data
}
func isEqualTo(other: Pattern) -> Bool
{
guard let other = other as? Foo else { return false }
return self.data == other.data
}
}
struct Bar: Pattern
{
let data: String
init(data: String)
{
self.data = data
}
func isEqualTo(other: Pattern) -> Bool
{
guard let other = other as? Bar else { return false }
return self.data == other.data
}
}
let a = Foo(data: "jeremyp")
let b = Bar(data: "jeremyp")
let c = Foo(data: "jeremyp")
let d = Foo(data: "jeremy")
let comp1 = a == c // true
let comp2 = a == b // false
let comp3 = a == d // false
let array1: [Pattern] = [a, b, c]
let array2: [Pattern] = [a, b, a]
let array3: [Pattern] = [a, d, c]
let comp4 = array1 == array2 // true
let comp5 = array1 == array3 // false
所以答案就是不要让模式协议从Equatable继承?我尝试了很多方法,结果证明这是最简单的。如果
Pattern
不可equalable
,则无法比较Pattern
的数组,因此必须为数组创建自己的相等运算符。实际上,在尝试从equalable继承之前,我曾经这样做过。我不知道我为什么忘了。谢谢你的帮助。Swift正在警告我关于数组的=
函数<协议的代码>成员运算符“==”必须至少有一个类型为Self的参数。有什么想法吗?