ПрограммированиеiOS/Swift разработчик

Поясните, как работает subscript в Swift, какие правила его объявления и вызова, и чем он отличается от обычных методов или computed properties?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

История вопроса:

Subscript был введён в Swift для удобной и безопасной работы с коллекциями и структурами данных, позволяя обращаться к элементам с помощью знакомого синтаксиса квадратных скобок.

Проблема:

Путаница между subscript, методами и computed свойствами, их областью применения, а также ошибочное использование subscript для доступа к данным, которые не являются коллекциями или имеют побочный эффект.

Решение:

Subscript — специальный механизм, позволяющий предоставить доступ к элементам объекта с помощью квадратных скобок. Он может быть read-only или read-write и поддерживает параметры любой природы: не только Int, но и String или свои типы.

Пример кода:

struct Matrix { private var data: [[Int]] init(rows: Int, columns: Int) { data = Array(repeating: Array(repeating: 0, count: columns), count: rows) } subscript(row: Int, column: Int) -> Int { get { data[row][column] } set { data[row][column] = newValue } } } var matrix = Matrix(rows: 2, columns: 2) matrix[0, 1] = 5 print(matrix[0, 1]) // 5

Ключевые особенности:

  • Позволяет переопределять (overload) subscript по необходимости, в том числе делать несколько с разными параметрами.
  • В отличие от методов, subscript всегда вызывается через квадратные скобки.
  • Может возвращать значения любых типов, поддерживает как чтение, так и запись.

Вопросы с подвохом.

Может ли subscript иметь более одного параметра?

Да, subscript может принимать любой набор параметров и любого типа (например, tuple).

Пример кода:

// См. пример выше с Matrix, где subscript(row: Int, column: Int)

Можно ли реализовать subscript только для чтения (read-only)?

Да, если не объявлять set, subscript будет только для чтения.

Пример кода:

struct ReadOnlyArray { private let items = [1, 2, 3] subscript(index: Int) -> Int { return items[index] } }

В чём разница между subscript и computed property?

Computed property всегда имеет фиксированное имя и не принимает параметров. Subscript позволяет обращаться по переменному индексу, имитируя коллекционную структуру.

Типовые ошибки и анти-паттерны

  • Использование subscript для операций с побочными эффектами (например, изменять глобальные переменные).
  • Неявная обработка выхода за границы индекса (crash вместо безопасного поведения).
  • Путают subscript и методы без видимой на то причины.

Пример из жизни

Негативный кейс

В custom-структуре subscript используется для изменения глобального состояния, что вызывает неожиданные сайд-эффекты при простом обращении к элементу в массиве.

Плюсы:

  • Краткость

Минусы:

  • Неочевидные побочные эффекты
  • Трудно отлаживать

Позитивный кейс

Используется subscript только для работы с приватным массивом внутри структуры, реализована обработка выхода за границы с возвратом nil.

Плюсы:

  • Логично и безопасно
  • Легко отлаживать
  • Код легко читать

Минусы:

  • Нужно добавить явную обработку ошибок, если необходимо