将下标添加到受约束的数组

时间:2016-03-08 09:09:59

标签: swift generics swift-extensions

鉴于结构Parameter具有namevalue属性,我想向数组添加一个下标,让我返回 name 匹配下标参数的第一个找到的元素。

用法示例:

let params = [Parameter("firstName", "John"), Parameter("lastName", "Doh")]    
let value = params["firstName"] // returns "John"

修改 如果我按如下方式定义数组,则仅发生编译器错误:

let params: [ParameterType] = [Parameter("firstName", "John"), Parameter("lastName", "Doh")]    
let value = params["firstName"] // returns "John"

现在,当我实现它时,我收到编译器错误:

error: ambiguous reference to member 'subscript'
        let value = params["firstName"] // returns "John"
                    ^~~~~~

note: found this candidate
    public subscript (index: Int) -> Element { get set }

note: found this candidate
    public subscript (name: String) -> String? { get set }

note: found this candidate
    public subscript (bounds: Range<Self.Index>) -> MutableSlice<Self> { get set }

note: found this candidate
    public subscript (position: Self.Index) -> Self.Base.Generator.Element { get }

那么,为什么这个含糊不清?

这对我没有意义。

注意:所有其他候选项都是标准库中定义的struct Array的实现。

例如如何

subscript (index: Int) -> Element

subscript (name: String) -> String?

暧昧?

我怀疑,错误消息只是令人困惑,而真正的错误是因为未完全指定类型参数Element。无论如何,这怎么可能实现?

这是我尝试实施它。

我知道 - 由于语言的当前限制 - 下标实现实际上是为符合ParameterType的元素类型的定义的:

public protocol ParameterType {
    init(_ name: String, _ value: String)
    var name: String { get }
    var value: String { get }
}

public extension Array where Element: ParameterType {

    subscript(name: String) -> String? {
        get {
            let a = self.filter { $0.name == name }
            if let e = a.first {
                return e.value
            } else {
                return nil
            }
        }
        set(newValue) {
            let i = self.index { $0.name == name }
            if let index = i {
                if let value = newValue {
                    self[index] = Element(name, value)
                } else {
                    self.remove(at:index)
                }
            } else {
                if let value = newValue {
                    let param = Element(name, value)
                    self.append(param)
                } else { /* */ }
            }
        }
    }

}

这是一个符合ParameterType的具体类型:

public struct Parameter: ParameterType {
    public init(_ name: String, _ value: String) {
        self.name = name
        self.value = value
    }
    public var name: String
    public var value: String
}

注意:

将数组约束到类型并不能解决它:将发出相同的错误。

0 个答案:

没有答案