class AnyComparable 继承自 class AnyEquatable

class AnyComparable inherits from class AnyEquatable

public class AnyEquatable: Equatable {
    public let value: Any
    private let equals: (Any) -> Bool

    public init<E: Equatable>(_ value: E) {
        self.value = value
        self.equals = { [=12=] as? E == value }
    }

    public static func == (lhs: AnyEquatable, rhs: AnyEquatable) -> Bool {
        lhs.equals(rhs.value) || rhs.equals(lhs.value)
    }
}

public class AnyComparable: AnyEquatable, Comparable {
    private let compares: (Any) -> Bool

    public init<C: Comparable>(_ value: C) {
        super.init(value)
        self.compares = { ([=12=] as? C).map { [=12=] < value } ?? false }
    }

    public static func < (lhs: AnyComparable, rhs: AnyComparable) -> Bool {
        lhs.compares(rhs.value) || rhs.compares(lhs.value)
    }
}

我有一个错误:

Overridden method 'init' has generic signature C where C: Comparable which is incompatible with base method's generic signature E where E: Equatable; expected generic signature to be C where C: Equatable

为什么编译器认为我重写了初始化程序?我没有使用“覆盖”这个词。我不能在这里重写,因为方法 'init' 有不同的签名(编译器告诉自己)。这不是压倒一切的。我希望子类使用它自己的初始化器,而且我(显然)不想继承超类初始化器。
那么,我该如何实现呢?有什么比可比较的东西继承自可等同的东西更自然的了!为什么我不能那样做?

请注意,子class 中的初始化程序确实覆盖了超级class中的初始化程序。如果您按照编译器的要求修复 C 上的约束,编译器接下来会告诉您的是您缺少 override 关键字。

这种行为是相当一致的,所以看起来像是故意设计的,在确定一种方法是否覆盖另一种方法时不考虑通用约束。这是另一个例子:

class A {
    func f<T>(t: T) {}
}

class B: A {
    func f<C: Equatable>(t: C) {} // error
}

无论如何,解决此问题的一种方法是仅更改参数标签:

public init<C: Comparable>(comparable value: C) {
    self.compares = { ([=11=] as? C).map { [=11=] < value } ?? false }
    super.init(value)
}

这样做的缺点是客户端代码变得不够简洁。每次都得做AnyComparable(comparable: something),挺长的。一种解决方案是将 AnyEquatableAnyComparable 放在同一个文件中,使两个初始化程序都成为 fileprivate。然后,您可以提供创建这些 classes 的工厂函数(在同一文件中)。例如:

public extension Equatable {
    func toAnyEquatable() -> AnyEquatable {
        .init(equatable: self)
    }
}

public extension Comparable {
    func toAnyComparable() -> AnyComparable {
        .init(comparable: self)
    }
}

另请注意,您对 < 的实施没有多大意义。应该是:

public static func < (lhs: AnyComparable, rhs: AnyComparable) -> Bool {
    lhs.compares(rhs.value) || (rhs != lhs && !rhs.compares(lhs.value))
}

compares应该表示“小于”,

self.compares = { ([=14=] as? C).map { value < [=14=] } ?? false }

说“lhs < rhs 或 rhs > lhs”。

但即便如此,在某些情况下,将此 class 与完全不相关的类型一起使用仍然没有多大意义,仅供参考:

let a = AnyComparable(comparable: "foo")
let b = AnyComparable(comparable: 1)
print(a < b) // true
print(a > b) // true
print(a <= b) // false
print(a >= b) // false
print(a == b) // false

所以请大家注意!