Subscripts в Swift позволяют предоставлять доступ к значениям типа по ключу или индексу схожим образом с массивами или словарями, но для любых своих собственных типов. Синтаксис похож на функцию, но доступ осуществляется в скобках: object[key].
Особенности:
get, либо get и set).Применение:
Пример: Двумерный массив (матрица) и subscript с двумя параметрами:
struct Matrix { let rows: Int, columns: Int private var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } subscript(row: Int, column: Int) -> Double { get { precondition(isValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] } set { precondition(isValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } private func isValid(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } } var matrix = Matrix(rows: 2, columns: 2) matrix[0,1] = 5.0 print(matrix[0,1]) // 5.0
Может ли subscript иметь параметр типа inout или быть mutating в структуре?
Ответ:
inout.mutating set, что позволяет изменять self внутри set:struct Counter { var value: Int = 0 subscript(increment: Bool) -> Int { mutating get { value += increment ? 1 : -1 return value } } }
История
В кастомной коллекции забыли сделать set в subscript mutating в структуре, в результате любая попытка изменять элемент через subscript вызывала ошибку компиляции. Ошибка проявилась на этапе интеграции коллекции после долгой отладки.
История
В кастомном subscript не реализовали корректную обработку выхода за границы индекса, что вызвало краши при обращении за пределы диапазона. В результате падали бизнес-критичные функции обработки данных.
История
Реализовали subscript с двумя параметрами у enum для кеширования, но не учли, что subscript не может быть static (у типа), а только у экземпляра. Архитектурное решение оказалось ошибочным, пришлось переписывать API взаимодействия коллекции.