问题描述
我有以下Protocol
:
protocol Cacheable {
//....//
func identifier() -> String
}
我可以使Cacheable
实现Equatable吗?
Can I make Cacheable
implements Equatable ?
当我执行以下操作时:
extension Cacheable: Equatable {}
func ==(lhs:Cacheable,rhs:Cacheable) -> Bool {
return lhs.identifier() == rhs.identifier()
}
我收到此错误消息:协议Cacheable
的扩展不能有继承子句
I got this error message : Extension of protocol Cacheable
cannot have an inheritance clause
推荐答案
1)允许比较两个相同类型的Cacheable
protocol Cacheable: Equatable {
//....//
func identifier() -> String
}
func ==<T : Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() == rhs.identifier()
}
专业人士
这是最简单的解决方案.
Pros
This is the simplest solution.
您只能比较两个相同类型的Cacheable
对象.这意味着下面的代码将失败,为了对其进行修复,您需要使Animal
符合Cacheable
:
You can only compare two Cacheable
objects of the same type. This means that code below will fail and in order to fix it you need to make Animal
conform to Cacheable
:
class Animal {
}
class Dog: Animal,Cacheable {
func identifier() -> String {
return "object"
}
}
class Cat: Animal,Cacheable {
func identifier() -> String {
return "object"
}
}
let a = Dog()
let b = Cat()
a == b //such comparison is not allowed
2)允许比较任何类型的Cacheable
protocol Cacheable:Equatable {
//....//
func identifier() -> String
}
func ==<T:Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=<T:Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() != rhs.identifier()
}
func ==<T:Cacheable, U:Cacheable>(lhs: T, rhs: U) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=<T:Cacheable, U:Cacheable>(lhs: T, rhs: U) -> Bool {
return lhs.identifier() != rhs.identifier()
}
专业人士
消除了上述解决方案1的局限性.现在,您可以轻松比较Dog
和Cat
.
- 实施时间更长.实际上,我不确定为什么仅指定
==
函数是不够的-这可能是编译器的错误.无论如何,您必须同时提供==
和!=
的实现. - 在某些情况下,此实现的好处也可能会带来问题,因为您允许在绝对不同的对象之间进行比较,并且编译器完全可以这样做.
- Implementation is longer. Actually I am not sure why specifying only
==
functions is not sufficient - this might be a bug with a compiler. Anyway, you have to provide the implementation for both==
and!=
. - In some cases the benefit of this implementation may also pose a problem as you are allowing the comparison between absolutely different objects and compiler is totally OK with it.
protocol Cacheable {
//....//
func identifier() -> String
}
func ==(lhs: Cacheable, rhs: Cacheable) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=(lhs: Cacheable, rhs: Cacheable) -> Bool {
return lhs.identifier() != rhs.identifier()
}
专业人士
您可以使用Cacheable
作为类型,而无需任何泛型.这引入了全新的可能性.例如:
Pros
You can use Cacheable
as type without needing any generics. This introduces a whole new range of possibilities. For example:
let c:[Cacheable] = [Dog(),RaceCar()]
c[0] == c[1]
c[0] != c[1]
对于解决方案1和2,此类代码将失败,并且您将不得不在类中使用泛型.但是,在最新的实现中,Cacheable
被视为类型,因此您可以声明类型为[Cacheable]
的数组.
With solutions 1 and 2 such code would fail and you would have to use generics in your classes. However, with the latest implementation Cacheable
is treated as a type, so you are allowed to declare an array of type [Cacheable]
.
您不再声明符合Equatable
,因此任何接受Equatable
参数的函数将不接受Cacheable
.显然,除了==
和!=
,我们在Cacheable
s中声明了它们.
You no longer declare conformance to Equatable
so any functions which accept Equatable
parameters will not accept Cacheable
. Obviously, apart from ==
and !=
as we declared them for Cacheable
s.
如果这不是您的代码中的问题,我实际上会更喜欢此解决方案.在许多情况下,能够将协议视为类型非常有用.
If this is not a problem in your code I would actually prefer this solution. Being able to treat protocol as a type is super useful in many cases.
这篇关于斯威夫特协议实现平等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!