> For the complete documentation index, see [llms.txt](https://swift.unicorndonkeys.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://swift.unicorndonkeys.com/guida-al-linguaggio/subscript.md).

# Subscript (Subscripts)

Accedi agli elementi di una collezione.

Classi, strutture ed enumerazioni possono definire dei *subscript*, che sono scorciatoie per accedere agli elementi membri di una collezione, di un elenco o di una sequenza. Usi i subscript per impostare e recuperare valori tramite un indice senza bisogno di metodi separati per l'impostazione e il recupero. Per esempio, accedi agli elementi di un'istanza di `Array` con `someArray[index]` e agli elementi di un'istanza di `Dictionary` con `someDictionary[key]`.

Puoi definire più subscript per un singolo tipo, e l'overload del subscript appropriato da usare viene selezionato in base al tipo del valore di indice che passi al subscript. I subscript non sono limitati a una sola dimensione, e puoi definire subscript con più parametri di input per soddisfare le esigenze del tuo tipo personalizzato.

## Sintassi dei subscript <a href="#sintassi-dei-subscript" id="sintassi-dei-subscript"></a>

I subscript ti permettono di interrogare le istanze di un tipo scrivendo uno o più valori tra parentesi quadre dopo il nome dell'istanza. La loro sintassi è simile sia alla sintassi dei metodi di istanza sia a quella delle proprietà calcolate. Scrivi le definizioni dei subscript con la parola chiave `subscript`, e specifichi uno o più parametri di input e un tipo di ritorno, nello stesso modo dei metodi di istanza. A differenza dei metodi di istanza, i subscript possono essere di lettura e scrittura o di sola lettura. Questo comportamento viene espresso da un getter e un setter nello stesso modo delle proprietà calcolate:

```swift
subscript(index: Int) -> Int {
    get {
        // Restituisci qui un valore di subscript appropriato.
    }
    set(newValue) {
        // Esegui qui un'azione di impostazione adeguata.
    }
}
```

Il tipo di `newValue` è lo stesso del valore di ritorno del subscript. Come per le proprietà calcolate, puoi scegliere di non specificare il parametro `(newValue)` del setter. Al tuo setter viene fornito un parametro predefinito chiamato `newValue` se non ne fornisci uno tu.

Come per le proprietà calcolate di sola lettura, puoi semplificare la dichiarazione di un subscript di sola lettura rimuovendo la parola chiave `get` e le sue parentesi graffe:

```swift
subscript(index: Int) -> Int {
    // Restituisci qui un valore di subscript appropriato.
}
```

Ecco un esempio di implementazione di un subscript di sola lettura, che definisce una struttura `TimesTable` per rappresentare una tabellina del *n* di numeri interi:

```swift
struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// Stampa "six times three is 18".
```

In questo esempio, viene creata una nuova istanza di `TimesTable` per rappresentare la tabellina del tre. Ciò viene indicato passando un valore di `3` all'`initializer` della struttura come valore da usare per il parametro `multiplier` dell'istanza.

Puoi interrogare l'istanza `threeTimesTable` chiamando il suo subscript, come mostrato nella chiamata `threeTimesTable[6]`. Questa richiede la sesta voce della tabellina del tre, che restituisce un valore di `18`, ovvero `3` per `6`.

{% hint style="info" %}
**Nota:** Una tabellina del *n* si basa su una regola matematica fissa. Non è appropriato impostare `threeTimesTable[someIndex]` a un nuovo valore, e quindi il subscript di `TimesTable` è definito come subscript di sola lettura.
{% endhint %}

## Uso dei subscript <a href="#uso-dei-subscript" id="uso-dei-subscript"></a>

Il significato esatto di “subscript” dipende dal contesto in cui viene usato. I subscript sono tipicamente usati come scorciatoia per accedere agli elementi membri di una collezione, di un elenco o di una sequenza. Sei libero di implementare i subscript nel modo più appropriato per la funzionalità della tua specifica classe o struttura.

Per esempio, il tipo `Dictionary` di Swift implementa un subscript per impostare e recuperare i valori memorizzati in un'istanza di `Dictionary`. Puoi impostare un valore in un dizionario fornendo una chiave del tipo di chiave del dizionario tra le parentesi del subscript, e assegnando al subscript un valore del tipo di valore del dizionario:

```swift
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
```

L'esempio qui sopra definisce una variabile chiamata `numberOfLegs` e la inizializza con un letterale dizionario contenente tre coppie chiave-valore. Il tipo del dizionario `numberOfLegs` viene inferito come `[String: Int]`. Dopo aver creato il dizionario, questo esempio usa l'assegnamento tramite subscript per aggiungere al dizionario una chiave `String` pari a `"bird"` e un valore `Int` pari a `2`.

Per maggiori informazioni sull'uso dei subscript con `Dictionary`, vedi [Accedere a un dizionario e modificarlo](/guida-al-linguaggio/tipi-collezione.md#accedere-a-un-dizionario-e-modificarlo).

{% hint style="info" %}
**Nota:** Il tipo `Dictionary` di Swift implementa il suo subscript chiave-valore come un subscript che accetta e restituisce un tipo *opzionale*. Per il dizionario `numberOfLegs` qui sopra, il subscript chiave-valore accetta e restituisce un valore di tipo `Int?`, ovvero “int opzionale”. Il tipo `Dictionary` usa un tipo di subscript opzionale per modellare il fatto che non tutte le chiavi avranno un valore, e per fornire un modo di eliminare il valore di una chiave assegnando un valore `nil` a quella chiave.
{% endhint %}

## Opzioni dei subscript <a href="#opzioni-dei-subscript" id="opzioni-dei-subscript"></a>

I subscript possono accettare un numero qualsiasi di parametri di input, e questi parametri di input possono essere di qualsiasi tipo. I subscript possono anche restituire un valore di qualsiasi tipo.

Come le funzioni, i subscript possono accettare un numero variabile di parametri e fornire valori predefiniti per i loro parametri, come discusso in [Parametri variadici](/guida-al-linguaggio/funzioni.md#parametri-variadici) e in [Valori predefiniti dei parametri](/guida-al-linguaggio/funzioni.md#valori-predefiniti-dei-parametri). Tuttavia, a differenza delle funzioni, i subscript non possono usare parametri in-out.

Una classe o una struttura può fornire tutte le implementazioni di subscript di cui ha bisogno, e il subscript appropriato da usare verrà inferito in base ai tipi del valore o dei valori contenuti tra le parentesi del subscript nel punto in cui il subscript viene usato. Questa definizione di più subscript è nota come *overload dei subscript*.

Sebbene la cosa più comune sia che un subscript accetti un solo parametro, puoi anche definire un subscript con più parametri se è appropriato per il tuo tipo. L'esempio seguente definisce una struttura `Matrix`, che rappresenta una matrice bidimensionale di valori `Double`. Il subscript della struttura `Matrix` accetta due parametri interi:

```swift
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` fornisce un inizializzatore che accetta due parametri chiamati `rows` e `columns`, e crea un array abbastanza grande da memorizzare `rows * columns` valori di tipo `Double`. A ogni posizione della matrice viene assegnato un valore iniziale di `0.0`. Per ottenere questo, la dimensione dell'array e un valore iniziale di cella di `0.0` vengono passati a un inizializzatore di array che crea e inizializza un nuovo array della dimensione corretta. Questo inizializzatore è descritto in modo più dettagliato in [Creare un array con un valore predefinito](/guida-al-linguaggio/tipi-collezione.md#creare-un-array-con-un-valore-predefinito).

Puoi costruire una nuova istanza di `Matrix` passando un numero di righe e di colonne appropriato al suo inizializzatore:

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

L'esempio qui sopra crea una nuova istanza di `Matrix` con due righe e due colonne. L'array `grid` di questa istanza di `Matrix` è di fatto una versione appiattita della matrice, letta dall'angolo in alto a sinistra a quello in basso a destra:

![](https://3581893755-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNzatREGwodw9Z93LQYJb%2Fuploads%2FuhCltQ0IBeW8OWeUyJ5B%2FsubscriptMatrix01%402x.png?alt=media)

I valori della matrice possono essere impostati passando al subscript i valori di riga e di colonna, separati da una virgola:

```swift
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
```

Queste due istruzioni chiamano il setter del subscript per impostare un valore di `1.5` nella posizione in alto a destra della matrice (dove `row` è `0` e `column` è `1`), e `3.2` nella posizione in basso a sinistra (dove `row` è `1` e `column` è `0`):

![](https://3581893755-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNzatREGwodw9Z93LQYJb%2Fuploads%2FajytOl7wfbgA2aK9mgoN%2FsubscriptMatrix02%402x.png?alt=media)

Il getter e il setter del subscript di `Matrix` contengono entrambi un'asserzione per verificare che i valori `row` e `column` del subscript siano validi. Per agevolare queste asserzioni, `Matrix` include un metodo di utilità chiamato `indexIsValid(row:column:)`, che verifica se i valori `row` e `column` richiesti si trovano all'interno dei limiti della matrice:

```swift
func indexIsValid(row: Int, column: Int) -> Bool {
    return row >= 0 && row < rows && column >= 0 && column < columns
}
```

Viene attivata un'asserzione se provi ad accedere a un subscript che si trova al di fuori dei limiti della matrice:

```swift
let someValue = matrix[2, 2]
// Questo attiva un'asserzione, perché [2, 2] è al di fuori dei limiti della matrice.
```

## Subscript di tipo <a href="#subscript-di-tipo" id="subscript-di-tipo"></a>

I subscript di istanza, come descritti sopra, sono subscript che chiami su un'istanza di un determinato tipo. Puoi anche definire subscript che vengono chiamati sul tipo stesso. Questo genere di subscript è chiamato *subscript di tipo*. Indichi un subscript di tipo scrivendo la parola chiave `static` prima della parola chiave `subscript`. Le classi possono invece usare la parola chiave `class`, per consentire alle sottoclassi di sovrascrivere l'implementazione di quel subscript della superclasse. L'esempio seguente mostra come definire e chiamare un subscript di tipo:

```swift
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)
```
