Расширение протокола Swift с AssociatedType, ограниченным коллекцией, не может использовать нижний индекс
Я пытаюсь написать протокол, который соответствует протоколу коллекции, и он имеет связанный тип - объект и объект свойства.
protocol DDCDataSource: Collection
{
associatedtype Object
var object: Object {get set}
}
Я хочу добавить некоторые функциональные возможности по умолчанию для случая, когда Object также соответствует протоколу Collection, а именно просто напрямую возвращать реализацию Object этих требуемых свойств и функций Collection. Кажется, что все это работает, за исключением требования коллекции для нижнего индекса.
Невозможно добавить значение типа "Self.Object" с индексом типа "Self.Object.Index"
extension DDCDataSource where Object: Collection
{
typealias Index = Object.Index
var startIndex: Object.Index {
get {
return object.startIndex
}
}
var endIndex: Object.Index {
get {
return object.endIndex
}
}
subscript(position: Object.Index) -> Element
{
return object[position]
}
func index(after i: Object.Index) -> Object.Index {
return object.index(after: i)
}
}
3 ответа
Краткий ответ: измените тип возвращаемого значения метода индекса Object.Element
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
или добавьте псевдоним типа (аналогично тому, как вы это делали для Index
тип)
typealias Element = Object.Element
subscript(position: Object.Index) -> Element {
return object[position]
}
Это заставляет код компилироваться и запускаться как ожидалось.
Пояснение: subscript
метод Collection
объявлен как
subscript(position: Self.Index) -> Self.Element { get }
где Self.Index
а также Self.Element
являются ассоциированными типами коллекции. С вашим кодом
subscript(position: Object.Index) -> Element {
return object[position]
}
компилятор выводит Self.Index
быть Object.Index
, но нет никакой связи между Self.Element
а также Object.Element
(который возвращается object[position]
). Ошибка становится более очевидной, если вы добавите явное приведение:
subscript(position: Object.Index) -> Element {
return object[position] as Element
}
Сейчас компилятор жалуется
ошибка: "Self.Object.Element" не конвертируется в "Self.Element"; Вы хотели использовать "как!" заставить опуститься?
Правильное решение - не принудительное приведение, а чтобы компилятор знал, что Self.Element
является Object.Element
, добавив псевдоним типа или изменив тип возвращаемого значения
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
так что компилятор выводит DDCDataSource.Element
быть Object.Element
,
Полный автономный пример: (Swift 4, Xcode 9 beta 6)
(Обратите внимание, что вы можете опустить get
ключевое слово для вычисляемых свойств только для чтения.)
protocol DDCDataSource: Collection {
associatedtype Object
var object: Object { get set }
}
extension DDCDataSource where Object: Collection {
var startIndex: Object.Index {
return object.startIndex
}
var endIndex: Object.Index {
return object.endIndex
}
subscript(position: Object.Index) -> Object.Element {
return object[position]
}
func index(after i: Object.Index) -> Object.Index {
return object.index(after: i)
}
}
struct MyDataSource: DDCDataSource {
var object = [1, 2, 3]
}
let mds = MyDataSource()
print(mds[1]) // 2
for x in mds { print(x) } // 1 2 3
Попробуй это:
subscript(position:Object.Index) -> Element
{
var element: Element
guard let elementObject = object[position] else {
//handle the case of 'object' being 'nil' and exit the current scope
}
element = elementObject as! Element
}
Во-первых, я думаю, что вы должны определить Element
,
Во-вторых, вы используете object[position]
Объект соответствует коллекции, но он не относится к типам коллекции. Очевидно, это не Array.
Как говорит яблоко: массив соответствует CustomDebugStringConvertible / CustomReflectable / CustomStringConvertible / CVarArg /Decodable / Encodable / ExpressibleByArrayLiteral /MutableCollection /RandomAccessCollection / RangeReplaceableCollection
Я думаю extension DDCDataSource where Object: Array
лучше.
И элемент в массиве должен быть Element
определены. Просто советы.