作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要比较符合协议(protocol) P
的结构数组。
P
不能符合 Equatable,因为它不能有“ self 要求”。
正在创建 AnyEquatable
作为类型删除是为此目的的常见做法。但是,AnyHashable
已经是标准库的一部分,并且符合 Equatable
。
我想知道 AnyEquatable
不是标准库的一部分是不是有充分的理由。是否应该使用标准 AnyHashable
而不是 AnyEquatable
?
最佳答案
AnyHashable包装了一堆通用功能。 AnyEquatable
没有;它的作用可以用一个闭包来表示。
let cupcake = "🧁"
let notCake = 0xca_e
let cupcakeEquals: (Any) -> Bool = try cupcake.getEquals()
XCTAssert( cupcakeEquals(cupcake) )
XCTAssertFalse( cupcakeEquals(notCake) )
let notCakeEquals = try notCake.getEquals(Any.self)
XCTAssert( notCakeEquals(notCake) )
XCTAssertFalse( notCakeEquals(cupcake) )
XCTAssertThrowsError( try cupcake.getEquals(Int.self) )
public extension Equatable {
/// A closure that equates another instance to this intance.
/// - Parameters:
/// - _: Use the metatype for `Castable` to avoid explicit typing.
/// - Throws: `CastError.impossible` if a `Castable` can't be cast to `Self`.
func getEquals<Castable>(_: Castable.Type = Castable.self) throws -> (Castable) -> Bool {
if let error = CastError(self, desired: Castable.self)
{ throw error }
return { self == $0 as? Self }
}
}
/// An error that represents casting gone wrong. 🧙♀️🙀
public enum CastError: Error {
/// An undesired cast is possible.
case possible
/// An desired cast is not possible.
case impossible
}
public extension CastError {
/// `nil` if an `Instance` can be cast to `Desired`. Otherwise, `.impossible`.
init?<Instance, Desired>(_: Instance, desired _: Desired.Type) {
self.init(Instance.self, desired: Desired.self)
}
/// `nil` if a `Source` can be cast to `Desired`. Otherwise, `.impossible`.
init?<Source, Desired>(_: Source.Type, desired _: Desired.Type) {
if Source.self is Desired.Type
{ return nil }
self = .impossible
}
/// `nil` if an `Instance` cannot be cast to `Undesired`. Otherwise, `.possible`.
init?<Instance, Undesired>(_: Instance, undesired _: Undesired.Type) {
self.init(Instance.self, undesired: Undesired.self)
}
/// `nil` if a `Source` cannot be cast to `Undesired`. Otherwise, `.possible`.
init?<Source, Undesired>(_: Source.Type, undesired _: Undesired.Type) {
guard Source.self is Undesired.Type
else { return nil }
self = .possible
}
}
您可以包装它,以符合 Equatable
,Cast
为 Any
。有用例吗?
/// A type-erased equatable value.
///
/// An `Equatable` instance is stored as a "`Cast`".
/// Only instances that can be cast to that type can be `==`'d with the `AnyEquatable`.
public struct AnyEquatable<Cast> {
public init<Equatable: Swift.Equatable>(_ equatable: Equatable) throws {
equals = try equatable.getEquals()
cast = equatable as! Cast
}
private let equals: (Cast) -> Bool
private let cast: Cast
}
extension AnyEquatable: Equatable {
public static func == (equatable0: Self, equatable1: Self) -> Bool {
equatable0 == equatable1.cast
}
}
public extension AnyEquatable {
static func == (equatable: Self, castable: Cast) -> Bool {
equatable.equals(castable)
}
static func == (castable: Cast, equatable: Self) -> Bool {
equatable.equals(castable)
}
}
let anyEquatable = try AnyEquatable<Any>(cupcake)
XCTAssertEqual( anyEquatable, try .init(cupcake) )
XCTAssert(anyEquatable == cupcake)
XCTAssertFalse(notCake == anyEquatable)
关于swift - AnyHashable 作为 AnyEquatable 的替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61375989/
我需要比较符合协议(protocol) P 的结构数组。 P 不能符合 Equatable,因为它不能有“ self 要求”。 正在创建 AnyEquatable作为类型删除是为此目的的常见做法。但是
我是一名优秀的程序员,十分优秀!