Классы, структуры и перечисления могут определять индексы , которые являются ярлыками для доступа к элементам-членам коллекции, списка или последовательности. Вы используете индексы для установки и извлечения значений по индексу, не требуя отдельных методов для установки и извлечения. Например, вы обращаетесь к элементам в 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"
Int
2
Для получения дополнительной информации о 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
предоставляет инициализатор, который принимает два параметра с именем rows
and 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)
0 комментариев