Добавление нижнего индекса в ограниченный массив
Учитывая структуру Parameter
который имеет name
и value
свойство, я хотел бы добавить Subscript в массив, который позволяет мне возвращать значение первого найденного элемента, имя которого соответствует параметру subscript.
Пример использования:
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 }
Итак, почему это неоднозначно?
Это не имеет смысла для меня.
Примечание: все остальные кандидаты являются реализациями для структуры 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
}
Замечания:
Ограничение массива типом класса не решает проблему: будут выдаваться те же ошибки.