如何传递到通用包装器结构中的基值? ExpressibleByArrayLiteral

问题描述

给定以下形式的通用包装器结构:

struct Observable<Base> {
    var base: Base
}

如何将应用于 Observable 类型值的功能传递到内部 Base?这可以很容易地完成,例如,使用 Equatable 协议,通过编写扩展,声明需求 func ==调用 Base 到 {{1} 的现有一致性},像这样:

Equatable

我怎么能对模式匹配做同样的事情,例如例如,这样我就可以直接对 extension Observable: Equatable where Base: Equatable { static func == (lhs: Observable<Base>,rhs: Observable<Base>) -> Bool { return lhs.base == rhs.base } } 类型的值进行 switch,就像如果它没有包含在 Observable<String?> 中一样?我想解决并看到工作的一个例子是:

Observable

额外问题:是否可以提供对 enum Availability { case available case notAvailable } let observableDescription = Observable<Availability>(.notAvailable) switch observableDescription { case .available: // … case .notAvailable: // … } 与泛型类型 ExpressibleByArrayLiteral 的一致性,以便我可以编写 Observable

解决方法

两个问题的两个结构

Expression Pattern

Equatable 实际上有 ~=(_:_:) 作为要求:

extension Observable: Equatable where Base: Equatable {
    static func == (lhs: Observable<Base>,rhs: Observable<Base>) -> Bool {
        return lhs.base == rhs.base
    }

    static func ~= (pattern: Base,value: Self) -> Bool {
        pattern ~= value.base
    }
}

现在你可以这样做:

let observableDescription = Observable<Availability>(base: .notAvailable)
switch observableDescription {
case .available:
    print("available")
case .notAvailable:
    print("notAvailable") // "notAvailable\n"
default:
    print("default")
}

ExpressibleByArrayLiteral

对于这个,你需要一个基本数组:

struct ObservableSequence<Base>: ExpressibleByArrayLiteral where Base: Sequence {
    var base: [Base.Element]
    init(arrayLiteral elements: Base.Element...) {
        base = Array(elements)
    }
}

用法:


let emptyCollection: ObservableSequence<[Int]> = []
print(emptyCollection.base) // "[]\n"
let collection: ObservableSequence<[Double]> = [1.0,3.0,7.0]
print(collection.base) // "[1.0,7.0]\n"