Краткий ответ: измените тип возвращаемого значения метода нижнего индекса на 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
- связанные типы `Collection. С вашим кодом
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
person
Martin R
schedule
10.09.2017
extension DDCDataSource where Object: RandomAccessCollection
, кажется, немного лучше. - person dengApro   schedule 09.09.2017_ = ["foo", "bar"][3]
во время выполнения. Тем не менее, мы не запрещаем Swift реализовывать индексы таким образом. - person Cœur   schedule 10.09.2017return object[position] as! Element
он вылетает во время выполнения. - person Martin R   schedule 10.09.2017subscript(test position: Object.Index) -> Element { return object[position] as! Element }
иextension Array: DDCDataSource { typealias Object = Array; var object: Array { get { return self } set { } } }
. Затем я проверяю иprint(["a", "b"][test: 1])
выводит b, в то время какprint(["a", "b"][test: 3])
выдает фатальную ошибку: индекс вне допустимого диапазона. - person Cœur   schedule 10.09.2017struct MyDataSource: DDCDataSource { var object = [1, 2, 3] }
иlet mds = MyDataSource() ; print(mds[1])
- В вашем примереObject.Element
иSelf.Element
идентичны, в общем случае это не так. - person Martin R   schedule 10.09.2017