Классы, структуры и перечисления могут определять индексы , которые являются ярлыками для доступа к элементам-членам коллекции, списка или последовательности. Вы используете индексы для установки и извлечения значений по индексу, не требуя отдельных методов для установки и извлечения. Например, вы обращаетесь к элементам в Arrayэкземпляре as someArray[index]и к элементам в Dictionaryэкземпляре as someDictionary[key].

Вы можете определить несколько подписок для одного типа, и соответствующая перегрузка нижнего индекса для использования выбирается в зависимости от типа значения индекса, которое вы передаете в индекс. Индексы не ограничиваются одним измерением, и вы можете определить индексы с несколькими входными параметрами в соответствии с потребностями вашего пользовательского типа.

Синтаксис нижнего индекса

Подстрочные индексы позволяют запрашивать экземпляры типа, записывая одно или несколько значений в квадратных скобках после имени экземпляра. Их синтаксис похож на синтаксис метода экземпляра и синтаксис вычисляемого свойства. Вы пишете определения индекса с помощью subscriptключевого слова и задаете один или несколько входных параметров и тип возвращаемого значения так же, как методы экземпляра. В отличие от методов экземпляра, подписки могут быть доступны только для чтения или записи. Это поведение передается геттером и сеттером так же, как и для вычисляемых свойств:

subscript(index: Int) -> Int {

get {

// Return an appropriate subscript value here.

}

set(newValue) {

// Perform a suitable setting action here.

}

}

Тип newValueсовпадает с возвращаемым значением нижнего индекса. Как и в случае с вычисленными свойствами, вы можете не указывать параметр сеттера (newValue). Вызываемый параметр по умолчанию newValueпредоставляется вашему установщику, если вы сами его не предоставляете.

Как и в случае вычисляемых свойств, доступных только для чтения, вы можете упростить объявление индекса только для чтения, удалив getключевое слово и его фигурные скобки:

subscript(index: Int) -> Int {

// Return an appropriate subscript value here.

}

Вот пример реализации только для чтения нижнего индекса, которая определяет TimesTableструктуру для представления n- кратной таблицы целых чисел:

struct TimesTable {

let multiplier: Int

subscript(index: Int) -> Int {

return multiplier * index

}

}

let threeTimesTable = TimesTable(multiplier: 3)

print("six times three is \(threeTimesTable[6])")

// Prints "six times three is 18"

В этом примере создается новый экземпляр TimesTableдля представления трехкратной таблицы. На это указывает передача значения 3структуры в initializerкачестве значения, используемого для параметра экземпляра multiplier.

Вы можете запросить threeTimesTableэкземпляр, вызвав его индекс, как показано в вызове threeTimesTable[6]. Это запрашивает шестую запись в таблице с тремя временами, которая возвращает значение 18или 3времена 6.

ЗАМЕТКА

Таблица n- times основана на фиксированном математическом правиле. Нецелесообразно устанавливать threeTimesTable[someIndex]новое значение, поэтому индекс для TimesTableопределяется как индекс только для чтения.

Использование индекса

Точное значение «подстрочный» зависит от контекста, в котором он используется. Подстрочные индексы обычно используются в качестве ярлыка для доступа к элементам-членам коллекции, списка или последовательности. Вы можете свободно реализовывать подписки наиболее подходящим образом для функциональности вашего конкретного класса или структуры.

Например, Dictionaryтип Swift реализует нижний индекс для установки и извлечения значений, хранящихся в Dictionaryэкземпляре. Вы можете установить значение в словаре, предоставив ключ типа ключа словаря в квадратных скобках и назначив значение типа словаря для индекса:

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]

numberOfLegs["bird"] = 2

В приведенном выше примере определяется переменная с именем numberOfLegsи инициализируется литералом словаря, содержащим три пары ключ-значение. Тип numberOfLegsсловаря подразумевается . После создания словаря этот пример использует присваивание индекса для добавления ключа и значения в словарь.[String: Int]String"bird"Int2

Для получения дополнительной информации о Dictionaryподписке .

ЗАМЕТКА

DictionaryТип Swift реализует свою подписку значения ключа как индекс, который принимает и возвращает необязательный тип. Для numberOfLegsсловаря выше, индекс значения ключа принимает и возвращает значение типа Int?, или «необязательный int». DictionaryТип использует дополнительный тип индекс модели тот факт , что не каждый ключ будет иметь значение, и дать способ , чтобы удалить значение ключа путем присвоения nilзначения для этого ключа.

Параметры нижнего индекса

Индексы могут принимать любое количество входных параметров, и эти входные параметры могут быть любого типа. Подписки также могут возвращать любой тип. Индексы могут использовать переменные параметры и предоставлять значения параметров по умолчанию, но они не могут использовать входящие и исходящие параметры.

Класс или структура может обеспечить столько реализаций нижнего индекса, сколько ему необходимо, и соответствующий используемый нижний индекс будет выведен на основе типов значения или значений, которые содержатся в квадратных скобках в точке, где используется нижний индекс. Это определение нескольких индексов известно как перегрузка индексов .

Хотя подстрочный индекс наиболее часто принимает один параметр, вы также можете определить подстрочный индекс с несколькими параметрами, если он подходит для вашего типа. В следующем примере определяется Matrixструктура, которая представляет собой двумерную матрицу Doubleзначений. В Matrixнижнем индексе структуры принимает два целочисленных параметра:

struct Matrix {

let rows: Int, columns: Int

var grid: [Double]

init(rows: Int, columns: Int) {

self.rows = rows

self.columns = columns

grid = Array(repeating: 0.0, count: rows * columns)

}

func indexIsValid(row: Int, column: Int) -> Bool {

return row >= 0 && row < rows && column >= 0 && column < columns

}

subscript(row: Int, column: Int) -> Double {

get {

assert(indexIsValid(row: row, column: column), "Index out of range")

return grid[(row * columns) + column]

}

set {

assert(indexIsValid(row: row, column: column), "Index out of range")

grid[(row * columns) + column] = newValue

}

}

}

Matrixпредоставляет инициализатор, который принимает два параметра с именем rowsand columns, и создает массив, достаточно большой для хранения значений типа . Каждой позиции в матрице присваивается начальное значение . Для этого размер массива и начальное значение ячейки передаются инициализатору массива, который создает и инициализирует новый массив правильного размера.

Вы можете создать новый Matrixэкземпляр, передав соответствующий счетчик строк и столбцов его инициализатору:

var matrix = Matrix(rows: 2, columns: 2)

В приведенном выше примере создается новый Matrixэкземпляр с двумя строками и двумя столбцами. gridМассив для этого Matrixэкземпляра эффективно уплощенной вариант матрицы, как прочитанный от верхнего левого до нижнего справа.

Значения в матрице могут быть установлены путем передачи значений строки и столбца в нижний индекс, разделенных запятой:

matrix[0, 1] = 1.5

matrix[1, 0] = 3.2

Эти два заявления называют сеттер подстрочного индекса, чтобы установить значение 1.5в правом верхнем положении матрицы (где rowесть 0и columnесть 1), а 3.2в нижнем левом положении (где rowнаходятся 1и columnесть 0).

В Matrixгеттере нижнего индекса и сеттер оба содержат утверждение , чтобы проверить , что подстрочные - х rowи columnзначения действительны. Чтобы помочь с этими утверждениями, Matrixвключается удобный метод, вызываемый indexIsValid(row:column:), который проверяет, находятся ли запрошенные rowи columnнаходятся ли в пределах матрицы:

func indexIsValid(row: Int, column: Int) -> Bool {

return row >= 0 && row < rows && column >= 0 && column < columns

}

Утверждение срабатывает, если вы пытаетесь получить доступ к нижнему индексу, который находится за пределами матрицы:

let someValue = matrix[2, 2]

// This triggers an assert, because [2, 2] is outside of the matrix bounds.

Тип подписки

Подписки экземпляра, как описано выше, являются подписками, которые вы вызываете для экземпляра определенного типа. Вы также можете определить индексы, которые вызываются для самого типа. Этот вид индекса называется типом индекса . Вы указываете индекс типа, написав staticключевое слово перед subscriptключевым словом. classВместо этого классы могут использовать ключевое слово, чтобы подклассы могли переопределить реализацию этого индекса в суперклассе. Пример ниже показывает, как вы определяете и вызываете индекс типа:

enum Planet: Int {

case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune

static subscript(n: Int) -> Planet {

return Planet(rawValue: n)!

}

}

let mars = Planet[4]

print(mars)