ProgramaciónDesarrollador iOS

Explique las características del trabajo con Subscripts en Swift. ¿Qué limitaciones existen para subscript, cómo se puede ampliar este mecanismo y dónde debe aplicarse? Proporcione un ejemplo de subscript no estándar.

Supere entrevistas con el asistente de IA Hintsage

Respuesta

Subscripts en Swift permiten proporcionar acceso a los valores de un tipo mediante una clave o un índice de manera similar a los arreglos o diccionarios, pero para cualquier tipo personalizado. La sintaxis es similar a una función, pero el acceso se realiza entre corchetes: object[key].

Características:

  • Una clase o estructura puede tener varios subscripts (sobrecarga por parámetros).
  • Un subscript puede ser solo de lectura o de lectura-escritura (contener solo get, o get y set).
  • Un subscript puede tener cualquier número de parámetros y tipos (por ejemplo, dos índices).
  • No hay soporte para parámetros variádicos.

Aplicación:

  • Para un acceso simplificado a colecciones, matrices, objetos personalizados, valores serializables, etc.

Ejemplo: Matriz bidimensional y subscript con dos parámetros:

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), "Índice fuera de rango") return grid[(row * columns) + column] } set { precondition(isValid(row: row, column: column), "Índice fuera de rango") 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

Pregunta engañosa

¿Puede un subscript tener un parámetro de tipo inout o ser mutating en una estructura?

Respuesta:

  • El parámetro de subscript no puede ser inout.
  • Un subscript en un tipo de valor (struct/enum) puede declararse como mutating set, lo que permite modificar self dentro de set:
struct Counter { var value: Int = 0 subscript(increment: Bool) -> Int { mutating get { value += increment ? 1 : -1 return value } } }

Ejemplos de errores reales debido al desconocimiento de los matices del tema


Historia

En una colección personalizada, olvidaron hacer que el set en el subscript fuera mutating en la estructura, como resultado, cualquier intento de modificar un elemento a través del subscript causaba un error de compilación. El error se manifestó en la etapa de integración de la colección después de una larga depuración.


Historia

En un subscript personalizado no implementaron un manejo correcto de la salida del rango del índice, lo que causó caídas al acceder más allá del rango. Como resultado, fallaron funciones críticas de negocio para el procesamiento de datos.


Historia

Implementaron un subscript con dos parámetros en un enum para caché, pero no consideraron que el subscript no puede ser static (en el tipo), sino solo en la instancia. La solución arquitectónica resultó ser errónea, tuvieron que reescribir la API de interacción de la colección.