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)
,挺长的。一种解决方案是将 AnyEquatable
和 AnyComparable
放在同一个文件中,使两个初始化程序都成为 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
所以请大家注意!
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)
,挺长的。一种解决方案是将 AnyEquatable
和 AnyComparable
放在同一个文件中,使两个初始化程序都成为 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
所以请大家注意!