Dan*_*ood 8 arrays protocols heterogeneous swift swift2
我遇到了一种我确定并不常见的情况.我有两个符合协议的对象数组,我想检查它们是否相等.
我真正想做的是:
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
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这会导致编译错误:
Error:(10, 30) protocol 'Pattern' can only be used as a generic constraint because it has Self or associated type requirements
基于这篇文章,我意识到我需要在协议上丢失Equatable继承并将其推送到具体的"Pattern"声明.虽然我真的不明白为什么.如果我通过重载来定义基于协议的两个对象是如何相等的==就我所见,确实没有问题.我甚至不需要知道实际类型或它们是类还是结构.
无论如何,这一切都很好,我现在可以比较,concretePattern.isEqualTo(otherConcretePattern)但问题仍然是我不能再比较这些对象的数组,就像我可以比较具体类型的数组,因为数组相等依赖于重载==运算符.
到目前为止,我设法做到的最好的isEqualTo方法是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) }
}
}
Run Code Online (Sandbox Code Playgroud)
真的没有别的办法吗?请告诉我,我错过了一些明显的东西.
我有两个符合协议的对象数组,我想检查它们是否相等.
所以你想说两个数组是相等的,如果它们中的所有元素都相等并且元素都符合模式.即
如果a,b,c和d都是符合Pattern的东西,那么你想要的
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
Run Code Online (Sandbox Code Playgroud)
最简单的方法是为两个模式阵列定义一个相等运算符,即
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
}
Run Code Online (Sandbox Code Playgroud)
我定义了两种符合Pattern的类型并尝试了各种相等的比较,它都有效
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
Run Code Online (Sandbox Code Playgroud)