Swift协议实现Equatable

Bob*_*j-C 34 protocols swift swift2 equatable

我有以下内容Protocol:

protocol Cacheable {
    //....//
    func identifier() -> String
}
Run Code Online (Sandbox Code Playgroud)

我可以使Cacheable工具Equatable吗?

当我做以下事情时:

extension Cacheable: Equatable {}

func ==(lhs:Cacheable,rhs:Cacheable) -> Bool {

     return lhs.identifier() == rhs.identifier()
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误消息:协议扩展Cacheable不能有继承子句

And*_*huk 46

1)允许比较两个Cacheable相同类型的s

protocol Cacheable: Equatable {
    //....//
    func identifier() -> String
}

func ==<T : Cacheable>(lhs: T, rhs: T) -> Bool {
    return lhs.identifier() == rhs.identifier()
}
Run Code Online (Sandbox Code Playgroud)

优点

这是最简单的解决方案.

缺点

您只能比较两个Cacheable相同类型的对象.这意味着下面的代码将失败,为了修复它,您需要Animal遵守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
Run Code Online (Sandbox Code Playgroud)

2)允许Cacheable比较任何类型的s

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()
}
Run Code Online (Sandbox Code Playgroud)

优点

删除上述解决方案1的限制.现在您可以轻松地比较DogCat.

缺点

  • 实施时间更长.实际上我不确定为什么只指定==函数是不够的 - 这可能是编译器的错误.无论如何,你必须提供两种实现==!=.
  • 在某些情况下,此实现的好处也可能会带来问题,因为您允许在绝对不同的对象之间进行比较,并且编译器完全可以使用它.

3)不符合 Equatable

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()
}
Run Code Online (Sandbox Code Playgroud)

优点

您可以使用Cacheable不需要任何泛型的类型.这引入了全新的可能性.例如:

let c:[Cacheable] = [Dog(),RaceCar()]

c[0] == c[1]
c[0] != c[1]
Run Code Online (Sandbox Code Playgroud)

对于解决方案1和2,此类代码将失败,您必须在类中使用泛型.但是,最新的实现Cacheable被视为一种类型,因此您可以声明一个类型的数组[Cacheable].

缺点

您不再声明符合性,Equatable因此任何接受Equatable参数的函数都不会接受Cacheable.显然,除了==!=为我们宣布他们为Cacheable秒.

如果这不是您的代码中的问题,我实际上更喜欢这个解决方案.能够将协议视为一种类型在许多情况下非常有用.

  • 这就是我使用泛型的原因;)这段代码有效.我现在使用Xcode 7 beta 5进行了测试 (2认同)
  • 这应该是接受的答案.在swift 2.1中完美运行 (2认同)

Jur*_*oga 11

尝试.

extension Equatable where Self : Cacheable {
}
Run Code Online (Sandbox Code Playgroud)