programowanieProgramista iOS

Wyjaśnij cechy działania z Subscriptami w Swift. Jakie są ograniczenia dla subscript, jak można rozszerzyć ten mechanizm i gdzie powinno się go zastosować? Podaj przykład nietypowego subscript.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

Subscript w Swift umożliwia dostęp do wartości typu za pomocą klucza lub indeksu w sposób podobny do tablic lub słowników, ale dla dowolnych własnych typów. Składnia jest podobna do funkcji, ale dostęp uzyskuje się w nawiasach: object[key].

Cechy:

  • Klasa lub struktura mogą mieć wiele subscript (przeciążanie według parametrów).
  • Subscript może być tylko do odczytu lub do odczytu i zapisu (zawierać tylko get, lub get i set).
  • Subscript może mieć dowolną liczbę parametrów i typów (na przykład dwa indeksy).
  • Brak wsparcia dla parametrów variadic.

Zastosowanie:

  • Do uproszczonego dostępu do kolekcji, macierzy, obiektów customowych, wartości serializowanych itd.

Przykład: Dwuwymiarowa tablica (macierz) i subscript z dwoma parametrami:

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), "Indeks poza zakresem") return grid[(row * columns) + column] } set { precondition(isValid(row: row, column: column), "Indeks poza zakresem") 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

Pytanie podchwytliwe

Czy subscript może mieć parametr typu inout lub być mutating w strukturze?

Odpowiedź:

  • Parametr subscript nie może być inout.
  • Subscript w typie wartości (struct/enum) może być zadeklarowany jako mutating set, co pozwala na modyfikację self wewnątrz set:
struct Counter { var value: Int = 0 subscript(increment: Bool) -> Int { mutating get { value += increment ? 1 : -1 return value } } }

Przykłady rzeczywistych błędów z powodu nieznajomości szczegółów tematu


Historia

W customowej kolekcji zapomniano zrobić set w subscript mutating w strukturze, w rezultacie każda próba zmiany elementu przez subscript kończyła się błędem kompilacji. Błąd ujawnił się na etapie integracji kolekcji po długim debugowaniu.


Historia

W customowym subscript nie zrealizowano poprawnej obsługi wyjścia poza zakres indeksu, co spowodowało awarie przy dostępie poza zakres. W rezultacie upadły krytyczne funkcje przetwarzania danych.


Historia

Zrealizowano subscript z dwoma parametrami dla enum do cachowania, ale nie uwzględniono, że subscript nie może być statyczny (dla typu), a tylko dla instancji. Rozwiązanie architektoniczne okazało się błędne, konieczne było przepisanie API interakcji kolekcji.