我有下面的Protocol:

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

我可以使Cacheable实现Equatable吗?

当我执行以下操作时:
extension Cacheable: Equatable {}

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

     return lhs.identifier() == rhs.identifier()
}

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

最佳答案

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

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

func ==<T : Cacheable>(lhs: T, rhs: T) -> Bool {
    return lhs.identifier() == rhs.identifier()
}

优点

这是最简单的解决方案。

缺点

您只能比较两个相同类型的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

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的限制。现在,您可以轻松比较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()
    }
    

    优点

    您可以将Cacheable用作类型,而无需任何泛型。这带来了全新的可能性。例如:
    let c:[Cacheable] = [Dog(),RaceCar()]
    
    c[0] == c[1]
    c[0] != c[1]
    

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

    缺点

    您不再声明符合Equatable,因此任何接受Equatable参数的函数都将不接受Cacheable。显然,除了==!=,我们为Cacheable声明了它们。

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

    关于swift - swift 协议(protocol)实现平等,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31921972/

    10-14 16:53
    查看更多