> 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/riferimento-del-linguaggio/tipi.md).

# Tipi (Types)

Usa i tipi con nome e i tipi composti integrati.

In Swift esistono due tipi di tipi: i tipi con nome e i tipi composti. Un *tipo con nome* è un tipo a cui può essere dato un nome particolare quando viene definito. I tipi con nome comprendono classi, strutture, enumerazioni e protocolli. Per esempio, le istanze di una classe definita dall'utente chiamata `MyClass` hanno il tipo `MyClass`. Oltre ai tipi con nome definiti dall'utente, la libreria standard di Swift definisce molti tipi con nome di uso comune, compresi quelli che rappresentano array, dizionari e valori opzionali.

I tipi di dati normalmente considerati di base o primitivi in altri linguaggi — come i tipi che rappresentano numeri, caratteri e stringhe — sono in realtà tipi con nome, definiti e implementati nella libreria standard di Swift usando strutture. Poiché sono tipi con nome, puoi estenderne il comportamento per soddisfare le esigenze del tuo programma, usando una dichiarazione di estensione, discussa in [Estensioni](/guida-al-linguaggio/estensioni.md) e in [Dichiarazione di estensione](/riferimento-del-linguaggio/dichiarazioni.md#dichiarazione-di-estensione).

Un *tipo composto* è un tipo senza nome, definito dal linguaggio Swift stesso. Esistono due tipi composti: i tipi funzione e i tipi tupla. Un tipo composto può contenere tipi con nome e altri tipi composti. Per esempio, il tipo tupla `(Int, (Int, Int))` contiene due elementi: il primo è il tipo con nome `Int`, e il secondo è un altro tipo composto `(Int, Int)`.

Puoi mettere delle parentesi attorno a un tipo con nome o a un tipo composto. Tuttavia, aggiungere parentesi attorno a un tipo non ha alcun effetto. Per esempio, `(Int)` equivale a `Int`.

Questo capitolo discute i tipi definiti dal linguaggio Swift stesso e descrive il comportamento dell'inferenza di tipo di Swift.

{% hint style="info" %}
**Grammatica di un tipo:**

*type* → *function-type*\
*type* → *array-type*\
*type* → *dictionary-type*\
*type* → *type-identifier*\
*type* → *tuple-type*\
*type* → *optional-type*\
*type* → *implicitly-unwrapped-optional-type*\
*type* → *protocol-composition-type*\
*type* → *opaque-type*\
*type* → *boxed-protocol-type*\
*type* → *metatype-type*\
*type* → *any-type*\
*type* → *self-type*\
*type* → **`(`** *type* **`)`**
{% endhint %}

## Annotazione di tipo <a href="#annotazione-di-tipo" id="annotazione-di-tipo"></a>

Un'*annotazione di tipo* specifica esplicitamente il tipo di una variabile o di un'espressione. Le annotazioni di tipo iniziano con i due punti (`:`) e terminano con un tipo, come mostrano gli esempi seguenti:

```swift
let someTuple: (Double, Double) = (3.14159, 2.71828)
func someFunction(a: Int) { /* ... */ }
```

Nel primo esempio, si specifica che l'espressione `someTuple` ha il tipo tupla `(Double, Double)`. Nel secondo esempio, si specifica che il parametro `a` della funzione `someFunction` ha il tipo `Int`.

Le annotazioni di tipo possono contenere un elenco opzionale di attributi di tipo prima del tipo.

{% hint style="info" %}
**Grammatica di un'annotazione di tipo:**

*type-annotation* → **`:`** *attributes?* *type*
{% endhint %}

## Identificatore di tipo <a href="#identificatore-di-tipo" id="identificatore-di-tipo"></a>

Un *identificatore di tipo* si riferisce a un tipo con nome oppure a un alias di tipo di un tipo con nome o composto.

Nella maggior parte dei casi, un identificatore di tipo si riferisce direttamente a un tipo con nome che ha lo stesso nome dell'identificatore. Per esempio, `Int` è un identificatore di tipo che si riferisce direttamente al tipo con nome `Int`, e l'identificatore di tipo `Dictionary<String, Int>` si riferisce direttamente al tipo con nome `Dictionary<String, Int>`.

Ci sono due casi in cui un identificatore di tipo non si riferisce a un tipo con lo stesso nome. Nel primo caso, un identificatore di tipo si riferisce a un alias di tipo di un tipo con nome o composto. Per esempio, nell'esempio seguente, l'uso di `Point` nell'annotazione di tipo si riferisce al tipo tupla `(Int, Int)`.

```swift
typealias Point = (Int, Int)
let origin: Point = (0, 0)
```

Nel secondo caso, un identificatore di tipo usa la sintassi a punto (`.`) per riferirsi a tipi con nome dichiarati in altri moduli o annidati all'interno di altri tipi. Per esempio, l'identificatore di tipo nel codice seguente fa riferimento al tipo con nome `MyType` dichiarato nel modulo `ExampleModule`.

```swift
var someValue: ExampleModule.MyType
```

{% hint style="info" %}
**Grammatica di un identificatore di tipo:**

*type-identifier* → *type-name* *generic-argument-clause?* | *type-name* *generic-argument-clause?* **`.`** *type-identifier*\
*type-name* → *identifier*
{% endhint %}

## Tipo tupla <a href="#tipo-tupla" id="tipo-tupla"></a>

Un *tipo tupla* è un elenco di tipi separati da virgole, racchiuso tra parentesi.

Puoi usare un tipo tupla come tipo di ritorno di una funzione per permettere alla funzione di restituire un'unica tupla contenente più valori. Puoi anche dare un nome agli elementi di un tipo tupla e usare quei nomi per riferirti ai valori dei singoli elementi. Il nome di un elemento è costituito da un identificatore seguito immediatamente da due punti (:). Per un esempio che dimostra entrambe queste caratteristiche, vedi [Funzioni con più valori di ritorno](/guida-al-linguaggio/funzioni.md#funzioni-con-piu-valori-di-ritorno).

Quando un elemento di un tipo tupla ha un nome, quel nome fa parte del tipo.

```swift
var someTuple = (top: 10, bottom: 12)  // someTuple è di tipo (top: Int, bottom: Int)
someTuple = (top: 4, bottom: 42) // OK: i nomi corrispondono.
someTuple = (9, 99)              // OK: i nomi vengono inferiti.
someTuple = (left: 5, right: 5)  // Errore: i nomi non corrispondono.
```

Tutti i tipi tupla contengono due o più tipi, tranne `Void`, che è un alias di tipo per il tipo tupla vuota, `()`.

{% hint style="info" %}
**Grammatica di un tipo tupla:**

*tuple-type* → **`(`** **`)`** | **`(`** *tuple-type-element* **`,`** *tuple-type-element-list* **`)`**\
*tuple-type-element-list* → *tuple-type-element* | *tuple-type-element* **`,`** *tuple-type-element-list*\
*tuple-type-element* → *element-name* *type-annotation* | *type*\
*element-name* → *identifier*
{% endhint %}

## Tipo funzione <a href="#tipo-funzione" id="tipo-funzione"></a>

Un *tipo funzione* rappresenta il tipo di una funzione, di un metodo o di una closure ed è costituito da un tipo di parametro e da un tipo di ritorno separati da una freccia (`->`):

```swift
(<#parameter type#>) -> <#return type#>
```

Il *parameter type* (tipo di parametro) è un elenco di tipi separati da virgole. Poiché il *return type* (tipo di ritorno) può essere un tipo tupla, i tipi funzione supportano funzioni e metodi che restituiscono più valori.

Un parametro del tipo funzione `() -> T` (dove `T` è un tipo qualsiasi) può applicare l'attributo `autoclosure` per creare implicitamente una closure nei suoi punti di chiamata. Questo fornisce un modo sintatticamente comodo per rinviare la valutazione di un'espressione senza dover scrivere una closure esplicita quando chiami la funzione. Per un esempio di parametro di tipo funzione autoclosure, vedi [Autoclosure](/guida-al-linguaggio/closure.md#autoclosure).

Un tipo funzione può avere parametri variadici nel suo *parameter type*. Sintatticamente, un parametro variadico è costituito da un nome di tipo base seguito immediatamente da tre punti (`...`), come in `Int...`. Un parametro variadico viene trattato come un array che contiene elementi del nome di tipo base. Per esempio, il parametro variadico `Int...` viene trattato come `[Int]`. Per un esempio che usa un parametro variadico, vedi [Parametri variadici](/guida-al-linguaggio/funzioni.md#parametri-variadici).

Per specificare un parametro in-out, anteponi al tipo del parametro la parola chiave `inout`. Non puoi contrassegnare con la parola chiave `inout` un parametro variadico o un tipo di ritorno. I parametri in-out sono discussi in [Parametri in-out](/guida-al-linguaggio/funzioni.md#parametri-in-out).

Se un tipo funzione ha un solo parametro e il tipo di quel parametro è un tipo tupla, allora il tipo tupla deve essere racchiuso tra parentesi quando si scrive il tipo della funzione. Per esempio, `((Int, Int)) -> Void` è il tipo di una funzione che accetta un unico parametro del tipo tupla `(Int, Int)` e non restituisce alcun valore. Al contrario, senza parentesi, `(Int, Int) -> Void` è il tipo di una funzione che accetta due parametri `Int` e non restituisce alcun valore. Allo stesso modo, poiché `Void` è un alias di tipo per `()`, il tipo funzione `(Void) -> Void` è uguale a `(()) -> ()` — una funzione che accetta un unico argomento che è una tupla vuota. Questi tipi non sono uguali a `() -> ()` — una funzione che non accetta argomenti.

I nomi degli argomenti nelle funzioni e nei metodi non fanno parte del tipo funzione corrispondente. Per esempio:

```swift
func someFunction(left: Int, right: Int) {}
func anotherFunction(left: Int, right: Int) {}
func functionWithDifferentLabels(top: Int, bottom: Int) {}

var f = someFunction // Il tipo di f è (Int, Int) -> Void, non (left: Int, right: Int) -> Void.
f = anotherFunction              // OK
f = functionWithDifferentLabels  // OK

func functionWithDifferentArgumentTypes(left: Int, right: String) {}
f = functionWithDifferentArgumentTypes     // Errore

func functionWithDifferentNumberOfArguments(left: Int, right: Int, top: Int) {}
f = functionWithDifferentNumberOfArguments // Errore
```

Poiché le etichette degli argomenti non fanno parte del tipo di una funzione, le ometti quando scrivi un tipo funzione.

```swift
var operation: (lhs: Int, rhs: Int) -> Int     // Errore
var operation: (_ lhs: Int, _ rhs: Int) -> Int // OK
var operation: (Int, Int) -> Int               // OK
```

Se un tipo funzione include più di una freccia (`->`), i tipi funzione vengono raggruppati da destra a sinistra. Per esempio, il tipo funzione `(Int) -> (Int) -> Int` viene inteso come `(Int) -> ((Int) -> Int)` — cioè, una funzione che accetta un `Int` e restituisce un'altra funzione che accetta e restituisce un `Int`.

I tipi funzione delle funzioni che possono lanciare o rilanciare un errore devono includere la parola chiave `throws`. Puoi includere un tipo tra parentesi dopo `throws` per specificare il tipo di errore che la funzione lancia. Il tipo dell'errore lanciato deve essere conforme al protocollo `Error`. Scrivere `throws` senza specificare un tipo equivale a scrivere `throws(any Error)`. Omettere `throws` equivale a scrivere `throws(Never)`. Il tipo di errore che una funzione lancia può essere qualsiasi tipo conforme a `Error`, compresi tipi generici, tipi protocollo boxed e tipi opachi.

Il tipo di errore che una funzione lancia fa parte del tipo di quella funzione, e una relazione di sottotipo tra tipi di errore significa che anche i tipi funzione corrispondenti sono sottotipi. Per esempio, se dichiari un tipo personalizzato `MyError`, la relazione tra alcuni tipi funzione è la seguente, dal supertipo al sottotipo:

1. Funzioni che lanciano qualsiasi errore, contrassegnate con `throws(any Error)`
2. Funzioni che lanciano un errore specifico, contrassegnate con `throws(MyError)`
3. Funzioni che non lanciano errori, contrassegnate con `throws(Never)`

Come conseguenza di queste relazioni di sottotipo:

* Puoi usare una funzione che non lancia errori negli stessi punti di una funzione che lancia errori.
* Puoi usare una funzione che lancia un tipo di errore concreto negli stessi punti di una funzione che lancia errori.
* Puoi usare una funzione che lancia un tipo di errore più specifico negli stessi punti di una funzione che lancia un tipo di errore più generale.

Se usi un tipo associato o un parametro di tipo generico come tipo dell'errore lanciato in un tipo funzione, allora a quel tipo associato o parametro di tipo generico è implicitamente richiesto di essere conforme al protocollo `Error`.

Le funzioni che lanciano e rilanciano errori sono descritte in [Funzioni e metodi throwing](/riferimento-del-linguaggio/dichiarazioni.md#funzioni-e-metodi-throwing) e in [Funzioni e metodi rethrowing](/riferimento-del-linguaggio/dichiarazioni.md#funzioni-e-metodi-rethrowing).

I tipi funzione delle funzioni asincrone devono essere contrassegnati con la parola chiave `async`. La parola chiave `async` fa parte del tipo di una funzione, e le funzioni sincrone sono sottotipi delle funzioni asincrone. Di conseguenza, puoi usare una funzione sincrona negli stessi punti di una asincrona. Per informazioni sulle funzioni asincrone, vedi [Funzioni e metodi asincroni](/riferimento-del-linguaggio/dichiarazioni.md#funzioni-e-metodi-asincroni).

### Restrizioni per le closure non-escaping <a href="#restrizioni-per-le-closure-non-escaping" id="restrizioni-per-le-closure-non-escaping"></a>

Un parametro che è una funzione non-escaping non può essere memorizzato in una proprietà, variabile o costante di tipo `Any`, perché questo potrebbe permettere al valore di sfuggire.

Un parametro che è una funzione non-escaping non può essere passato come argomento a un altro parametro funzione non-escaping. Questa restrizione aiuta Swift a eseguire più controlli sugli accessi in conflitto alla memoria in fase di compilazione anziché in fase di esecuzione. Per esempio:

```swift
let external: (() -> Void) -> Void = { _ in () }
func takesTwoFunctions(first: (() -> Void) -> Void, second: (() -> Void) -> Void) {
    first { first {} }       // Errore
    second { second {}  }    // Errore

    first { second {} }      // Errore
    second { first {} }      // Errore

    first { external {} }    // OK
    external { first {} }    // OK
}
```

Nel codice qui sopra, entrambi i parametri di `takesTwoFunctions(first:second:)` sono funzioni. Nessuno dei due parametri è contrassegnato con `@escaping`, quindi sono entrambi non-escaping.

Le quattro chiamate di funzione contrassegnate con "Errore" nell'esempio qui sopra causano errori del compilatore. Poiché i parametri `first` e `second` sono funzioni non-escaping, non possono essere passati come argomenti a un altro parametro funzione non-escaping. Al contrario, le due chiamate di funzione contrassegnate con "OK" non causano un errore del compilatore. Queste chiamate di funzione non violano la restrizione perché `external` non è uno dei parametri di `takesTwoFunctions(first:second:)`.

Se hai bisogno di evitare questa restrizione, contrassegna uno dei parametri come escaping, oppure converti temporaneamente uno dei parametri funzione non-escaping in una funzione escaping usando la funzione `withoutActuallyEscaping(_:do:)`. Per informazioni su come evitare gli accessi in conflitto alla memoria, vedi [Sicurezza della memoria](/guida-al-linguaggio/sicurezza-della-memoria.md).

{% hint style="info" %}
**Grammatica di un tipo funzione:**

*function-type* → *attributes?* *function-type-argument-clause* **`async`***?* *throws-clause?* **`->`** *type*

*function-type-argument-clause* → **`(`** **`)`**\
*function-type-argument-clause* → **`(`** *function-type-argument-list* **`...`***?* **`)`**

*function-type-argument-list* → *function-type-argument* | *function-type-argument* **`,`** *function-type-argument-list*\
*function-type-argument* → *attributes?* *parameter-modifier?* *type* | *argument-label* *type-annotation*\
*argument-label* → *identifier*

*throws-clause* → **`throws`** | **`throws`** **`(`** *type* **`)`**
{% endhint %}

## Tipo array <a href="#tipo-array" id="tipo-array"></a>

Il linguaggio Swift fornisce il seguente zucchero sintattico per il tipo `Array<Element>` della libreria standard di Swift:

```swift
[<#type#>]
```

In altre parole, le due dichiarazioni seguenti sono equivalenti:

```swift
let someArray: Array<String> = ["Alex", "Brian", "Dave"]
let someArray: [String] = ["Alex", "Brian", "Dave"]
```

In entrambi i casi, la costante `someArray` è dichiarata come array di stringhe. Agli elementi di un array si può accedere tramite subscript specificando un valore di indice valido tra parentesi quadre: `someArray[0]` si riferisce all'elemento all'indice 0, `"Alex"`.

Puoi creare array multidimensionali annidando coppie di parentesi quadre, dove il nome del tipo base degli elementi è contenuto nella coppia di parentesi quadre più interna. Per esempio, puoi creare un array tridimensionale di interi usando tre coppie di parentesi quadre:

```swift
var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
```

Quando accedi agli elementi di un array multidimensionale, l'indice di subscript più a sinistra si riferisce all'elemento a quell'indice nell'array più esterno. L'indice di subscript successivo a destra si riferisce all'elemento a quell'indice nell'array annidato un livello più all'interno. E così via. Ciò significa che, nell'esempio qui sopra, `array3D[0]` si riferisce a `[[1, 2], [3, 4]]`, `array3D[0][1]` si riferisce a `[3, 4]`, e `array3D[0][1][1]` si riferisce al valore 4.

Per una discussione dettagliata del tipo `Array` della libreria standard di Swift, vedi [Array](/guida-al-linguaggio/tipi-collezione.md#array).

{% hint style="info" %}
**Grammatica di un tipo array:**

*array-type* → **`[`** *type* **`]`**
{% endhint %}

## Tipo dizionario <a href="#tipo-dizionario" id="tipo-dizionario"></a>

Il linguaggio Swift fornisce il seguente zucchero sintattico per il tipo `Dictionary<Key, Value>` della libreria standard di Swift:

```swift
[<#key type#>: <#value type#>]
```

In altre parole, le due dichiarazioni seguenti sono equivalenti:

```swift
let someDictionary: [String: Int] = ["Alex": 31, "Paul": 39]
let someDictionary: Dictionary<String, Int> = ["Alex": 31, "Paul": 39]
```

In entrambi i casi, la costante `someDictionary` è dichiarata come dizionario con stringhe come chiavi e interi come valori.

Ai valori di un dizionario si può accedere tramite subscript specificando la chiave corrispondente tra parentesi quadre: `someDictionary["Alex"]` si riferisce al valore associato alla chiave `"Alex"`. Il subscript restituisce un valore opzionale del tipo di valore del dizionario. Se la chiave specificata non è contenuta nel dizionario, il subscript restituisce `nil`.

Il tipo della chiave di un dizionario deve essere conforme al protocollo `Hashable` della libreria standard di Swift.

Per una discussione dettagliata del tipo `Dictionary` della libreria standard di Swift, vedi [Dizionari](/guida-al-linguaggio/tipi-collezione.md#dizionari).

{% hint style="info" %}
**Grammatica di un tipo dizionario:**

*dictionary-type* → **`[`** *type* **`:`** *type* **`]`**
{% endhint %}

## Tipo opzionale <a href="#tipo-opzionale" id="tipo-opzionale"></a>

Il linguaggio Swift definisce il `?` postfisso come zucchero sintattico per il tipo con nome `Optional<Wrapped>`, definito nella libreria standard di Swift. In altre parole, le due dichiarazioni seguenti sono equivalenti:

```swift
var optionalInteger: Int?
var optionalInteger: Optional<Int>
```

In entrambi i casi, la variabile `optionalInteger` è dichiarata con il tipo di un intero opzionale. Nota che tra il tipo e il `?` non può comparire alcuno spazio bianco.

Il tipo `Optional<Wrapped>` è un'enumerazione con due casi, `none` e `some(Wrapped)`, che vengono usati per rappresentare valori che possono essere presenti o meno. Qualsiasi tipo può essere dichiarato esplicitamente come (o convertito implicitamente in) un tipo opzionale. Se non fornisci un valore iniziale quando dichiari una variabile o una proprietà opzionale, il suo valore è per impostazione predefinita `nil`.

Se un'istanza di un tipo opzionale contiene un valore, puoi accedere a quel valore usando l'operatore postfisso `!`, come mostrato di seguito:

```swift
optionalInteger = 42
optionalInteger! // 42
```

Usare l'operatore `!` per fare l'unwrapping di un opzionale che ha un valore `nil` produce un errore in fase di esecuzione.

Puoi anche usare l'optional chaining e l'optional binding per eseguire in modo condizionale un'operazione su un'espressione opzionale. Se il valore è `nil`, non viene eseguita alcuna operazione e quindi non viene prodotto alcun errore in fase di esecuzione.

Per maggiori informazioni e per vedere esempi che mostrano come usare i tipi opzionali, vedi [Opzionali](/guida-al-linguaggio/le-basi.md#opzionali).

{% hint style="info" %}
**Grammatica di un tipo opzionale:**

*optional-type* → *type* **`?`**
{% endhint %}

## Tipo opzionale con unwrapping implicito <a href="#tipo-opzionale-con-unwrapping-implicito" id="tipo-opzionale-con-unwrapping-implicito"></a>

Il linguaggio Swift definisce il `!` postfisso come zucchero sintattico per il tipo con nome `Optional<Wrapped>`, definito nella libreria standard di Swift, con il comportamento aggiuntivo che viene fatto automaticamente l'unwrapping quando vi si accede. Se provi a usare un opzionale con unwrapping implicito che ha un valore `nil`, otterrai un errore in fase di esecuzione. A eccezione del comportamento di unwrapping implicito, le due dichiarazioni seguenti sono equivalenti:

```swift
var implicitlyUnwrappedString: String!
var explicitlyUnwrappedString: Optional<String>
```

Nota che tra il tipo e il `!` non può comparire alcuno spazio bianco.

Poiché l'unwrapping implicito cambia il significato della dichiarazione che contiene quel tipo, i tipi opzionali annidati all'interno di un tipo tupla o di un tipo generico — come i tipi degli elementi di un dizionario o di un array — non possono essere contrassegnati come con unwrapping implicito. Per esempio:

```swift
let tupleOfImplicitlyUnwrappedElements: (Int!, Int!)  // Errore
let implicitlyUnwrappedTuple: (Int, Int)!             // OK

let arrayOfImplicitlyUnwrappedElements: [Int!]        // Errore
let implicitlyUnwrappedArray: [Int]!                  // OK
```

Poiché gli opzionali con unwrapping implicito hanno lo stesso tipo `Optional<Wrapped>` dei valori opzionali, puoi usare gli opzionali con unwrapping implicito in tutti gli stessi punti del tuo codice in cui puoi usare gli opzionali. Per esempio, puoi assegnare valori di opzionali con unwrapping implicito a variabili, costanti e proprietà di tipo opzionale, e viceversa.

Come per gli opzionali, se non fornisci un valore iniziale quando dichiari una variabile o una proprietà opzionale con unwrapping implicito, il suo valore è per impostazione predefinita `nil`.

Usa l'optional chaining per eseguire in modo condizionale un'operazione su un'espressione opzionale con unwrapping implicito. Se il valore è `nil`, non viene eseguita alcuna operazione e quindi non viene prodotto alcun errore in fase di esecuzione.

Per maggiori informazioni sui tipi opzionali con unwrapping implicito, vedi [Opzionali con unwrapping implicito](/guida-al-linguaggio/le-basi.md#opzionali-con-unwrapping-implicito).

{% hint style="info" %}
**Grammatica di un tipo opzionale con unwrapping implicito:**

*implicitly-unwrapped-optional-type* → *type* **`!`**
{% endhint %}

## Tipo composizione di protocolli <a href="#tipo-composizione-di-protocolli" id="tipo-composizione-di-protocolli"></a>

Un *tipo composizione di protocolli* definisce un tipo conforme a ciascun protocollo di un elenco di protocolli specificati, oppure un tipo che è una sottoclasse di una data classe ed è conforme a ciascun protocollo di un elenco di protocolli specificati. I tipi composizione di protocolli possono essere usati solo quando si specifica un tipo nelle annotazioni di tipo, nelle clausole dei parametri generici, e nelle clausole `where` generiche.

I tipi composizione di protocolli hanno la forma seguente:

```swift
<#Protocol 1#> & <#Protocol 2#>
```

Un tipo composizione di protocolli ti permette di specificare un valore il cui tipo è conforme ai requisiti di più protocolli senza definire esplicitamente un nuovo protocollo con nome che erediti da ciascun protocollo a cui vuoi che il tipo sia conforme. Per esempio, puoi usare il tipo composizione di protocolli `ProtocolA & ProtocolB & ProtocolC` invece di dichiarare un nuovo protocollo che erediti da `ProtocolA`, `ProtocolB` e `ProtocolC`. Allo stesso modo, puoi usare `SuperClass & ProtocolA` invece di dichiarare un nuovo protocollo che sia una sottoclasse di `SuperClass` e sia conforme a `ProtocolA`.

Ciascun elemento di un elenco di composizione di protocolli è uno dei seguenti; l'elenco può contenere al massimo una classe:

* Il nome di una classe
* Il nome di un protocollo
* Un alias di tipo il cui tipo sottostante è un tipo composizione di protocolli, un protocollo o una classe.

Quando un tipo composizione di protocolli contiene alias di tipo, è possibile che lo stesso protocollo compaia più di una volta nelle definizioni — i duplicati vengono ignorati. Per esempio, la definizione di `PQR` nel codice seguente equivale a `P & Q & R`.

```swift
typealias PQ = P & Q
typealias PQR = PQ & Q & R
```

{% hint style="info" %}
**Grammatica di un tipo composizione di protocolli:**

*protocol-composition-type* → *type-identifier* **`&`** *protocol-composition-continuation*\
*protocol-composition-continuation* → *type-identifier* | *protocol-composition-type*
{% endhint %}

## Tipo opaco <a href="#tipo-opaco" id="tipo-opaco"></a>

Un *tipo opaco* definisce un tipo conforme a un protocollo o a una composizione di protocolli, senza specificare il tipo concreto sottostante.

I tipi opachi compaiono come tipo di ritorno di una funzione o di un subscript, come tipo di un parametro di una funzione, di un subscript o di un inizializzatore, o come tipo di una proprietà. I tipi opachi non possono comparire come parte di un tipo tupla o di un tipo generico, come il tipo degli elementi di un array o il tipo racchiuso di un opzionale.

I tipi opachi hanno la forma seguente:

```swift
some <#constraint#>
```

Il *constraint* (vincolo) è un tipo classe, un tipo protocollo, un tipo composizione di protocolli, oppure `Any`. Un valore può essere usato come istanza del tipo opaco solo se è un'istanza di un tipo conforme al protocollo o alla composizione di protocolli elencati, o che eredita dalla classe elencata. Il codice che interagisce con un valore opaco può usare il valore solo nei modi che fanno parte dell'interfaccia definita dal *vincolo*.

In fase di compilazione, un valore il cui tipo è opaco ha un tipo concreto specifico, e Swift può usare quel tipo sottostante per le ottimizzazioni. Tuttavia, il tipo opaco forma un confine che le informazioni su quel tipo sottostante non possono attraversare.

Le dichiarazioni di protocollo non possono includere tipi opachi. Le classi non possono usare un tipo opaco come tipo di ritorno di un metodo non final.

Una funzione che usa un tipo opaco come tipo di ritorno deve restituire valori che condividono un unico tipo sottostante. Il tipo di ritorno può includere tipi che fanno parte dei parametri di tipo generici della funzione. Per esempio, una funzione `someFunction<T>()` potrebbe restituire un valore di tipo `T` o `Dictionary<String, T>`.

Scrivere un tipo opaco per un parametro è zucchero sintattico per l'uso di un tipo generico, senza specificare un nome per il parametro di tipo generico. Il parametro di tipo generico implicito ha un vincolo che richiede che sia conforme al protocollo indicato nel tipo opaco. Se scrivi più tipi opachi, ciascuno crea il proprio parametro di tipo generico. Per esempio, le dichiarazioni seguenti sono equivalenti:

```swift
func someFunction(x: some MyProtocol, y: some MyProtocol) { }
func someFunction<T1: MyProtocol, T2: MyProtocol>(x: T1, y: T2) { }
```

Nella seconda dichiarazione, poiché i parametri di tipo generici `T1` e `T2` hanno un nome, puoi fare riferimento a questi tipi e usarli altrove nel codice. Al contrario, i parametri di tipo generici della prima dichiarazione non hanno un nome e non possono essere referenziati in altro codice.

Non puoi usare un tipo opaco nel tipo di un parametro variadico.

Non puoi usare un tipo opaco come parametro di un tipo funzione che viene restituito, né come parametro in un tipo di parametro che è un tipo funzione. In queste posizioni, il chiamante della funzione dovrebbe costruire un valore di quel tipo sconosciuto.

```swift
protocol MyProtocol { }
func badFunction() -> (some MyProtocol) -> Void { }  // Errore
func anotherBadFunction(callback: (some MyProtocol) -> Void) { }  // Errore
```

{% hint style="info" %}
**Grammatica di un tipo opaco:**

*opaque-type* → **`some`** *type*
{% endhint %}

## Tipo protocollo boxed <a href="#tipo-protocollo-boxed" id="tipo-protocollo-boxed"></a>

Un *tipo protocollo boxed* definisce un tipo conforme a un protocollo o a una composizione di protocolli, con la possibilità che quel tipo conforme vari mentre il programma è in esecuzione.

I tipi protocollo boxed hanno la forma seguente:

```swift
any <#constraint#>
```

Il *constraint* (vincolo) è un tipo protocollo, un tipo composizione di protocolli, un metatipo di un tipo protocollo, oppure un metatipo di un tipo composizione di protocolli.

In fase di esecuzione, un'istanza di un tipo protocollo boxed può contenere un valore di qualsiasi tipo che soddisfi il *vincolo*. Questo comportamento contrasta con il modo in cui funzionano i tipi opachi, in cui esiste un tipo conforme specifico noto in fase di compilazione. Il livello aggiuntivo di indirezione usato quando si lavora con un tipo protocollo boxed è chiamato *boxing*. Il boxing richiede tipicamente un'allocazione di memoria separata per la memorizzazione e un livello aggiuntivo di indirezione per l'accesso, il che comporta un costo in termini di prestazioni in fase di esecuzione.

Applicare `any` ai tipi `Any` o `AnyObject` non ha alcun effetto, perché quei tipi sono già tipi protocollo boxed.

{% hint style="info" %}
**Grammatica di un tipo protocollo boxed:**

*boxed-protocol-type* → **`any`** *type*
{% endhint %}

## Tipo metatipo <a href="#tipo-metatipo" id="tipo-metatipo"></a>

Un *tipo metatipo* si riferisce al tipo di qualsiasi tipo, compresi i tipi classe, i tipi struttura, i tipi enumerazione e i tipi protocollo.

Il metatipo di un tipo classe, struttura o enumerazione è il nome di quel tipo seguito da `.Type`. Il metatipo di un tipo protocollo — non del tipo concreto conforme al protocollo in fase di esecuzione — è il nome di quel protocollo seguito da `.Protocol`. Per esempio, il metatipo del tipo classe `SomeClass` è `SomeClass.Type` e il metatipo del protocollo `SomeProtocol` è `SomeProtocol.Protocol`.

Puoi usare l'espressione postfissa `self` per accedere a un tipo come valore. Per esempio, `SomeClass.self` restituisce `SomeClass` stesso, non un'istanza di `SomeClass`. E `SomeProtocol.self` restituisce `SomeProtocol` stesso, non un'istanza di un tipo conforme a `SomeProtocol` in fase di esecuzione. Puoi chiamare la funzione `type(of:)` con un'istanza di un tipo per accedere al tipo dinamico, in fase di esecuzione, di quell'istanza come valore, come mostra l'esempio seguente:

```swift
class SomeBaseClass {
    class func printClassName() {
        print("SomeBaseClass")
    }
}
class SomeSubClass: SomeBaseClass {
    override class func printClassName() {
        print("SomeSubClass")
    }
}
let someInstance: SomeBaseClass = SomeSubClass()
// Il tipo in fase di compilazione di someInstance è SomeBaseClass,
// e il tipo in fase di esecuzione di someInstance è SomeSubClass
type(of: someInstance).printClassName()
// Stampa "SomeSubClass".
```

Per maggiori informazioni, vedi [`type(of:)`](https://developer.apple.com/documentation/swift/type\(of:\)) nella libreria standard di Swift.

Usa un'espressione di inizializzazione per costruire un'istanza di un tipo a partire dal valore metatipo di quel tipo. Per le istanze di classe, l'inizializzatore chiamato deve essere contrassegnato con la parola chiave `required` oppure l'intera classe deve essere contrassegnata con la parola chiave `final`.

```swift
class AnotherSubClass: SomeBaseClass {
    let string: String
    required init(string: String) {
        self.string = string
    }
    override class func printClassName() {
        print("AnotherSubClass")
    }
}
let metatype: AnotherSubClass.Type = AnotherSubClass.self
let anotherInstance = metatype.init(string: "some string")
```

{% hint style="info" %}
**Grammatica di un tipo metatipo:**

*metatype-type* → *type* **`.`** **`Type`** | *type* **`.`** **`Protocol`**
{% endhint %}

## Tipo Any <a href="#tipo-any" id="tipo-any"></a>

Il tipo `Any` può contenere valori di tutti gli altri tipi. `Any` può essere usato come tipo concreto per un'istanza di uno qualsiasi dei tipi seguenti:

* Una classe, una struttura o un'enumerazione
* Un metatipo, come `Int.self`
* Una tupla con componenti di qualsiasi tipo
* Un tipo closure o funzione

```swift
let mixed: [Any] = ["one", 2, true, (4, 5.3), { () -> Int in return 6 }]
```

Quando usi `Any` come tipo concreto per un'istanza, devi convertire l'istanza in un tipo noto prima di poter accedere alle sue proprietà o ai suoi metodi. Le istanze con un tipo concreto `Any` mantengono il loro tipo dinamico originale e possono essere convertite in quel tipo usando uno degli operatori di type cast — `as`, `as?` o `as!`. Per esempio, usa `as?` per eseguire il downcast condizionale del primo oggetto di un array eterogeneo a una `String` come segue:

```swift
if let first = mixed.first as? String {
    print("The first item, '\(first)', is a string.")
}
// Stampa "The first item, 'one', is a string."
```

Per maggiori informazioni sulle conversioni, vedi [Type casting](/guida-al-linguaggio/type-casting.md).

Il protocollo `AnyObject` è simile al tipo `Any`. Tutte le classi sono implicitamente conformi ad `AnyObject`. A differenza di `Any`, che è definito dal linguaggio, `AnyObject` è definito dalla libreria standard di Swift. Per maggiori informazioni, vedi [Protocolli riservati alle classi](/guida-al-linguaggio/protocolli.md#protocolli-riservati-alle-classi) e [`AnyObject`](https://developer.apple.com/documentation/swift/anyobject).

{% hint style="info" %}
**Grammatica di un tipo Any:**

*any-type* → **`Any`**
{% endhint %}

## Tipo Self <a href="#tipo-self" id="tipo-self"></a>

Il tipo `Self` non è un tipo specifico, ma ti permette piuttosto di riferirti comodamente al tipo corrente senza ripetere o conoscere il nome di quel tipo.

In una dichiarazione di protocollo o nella dichiarazione di un membro di un protocollo, il tipo `Self` si riferisce al tipo che alla fine sarà conforme al protocollo.

In una dichiarazione di struttura, classe o enumerazione, il tipo `Self` si riferisce al tipo introdotto dalla dichiarazione. All'interno della dichiarazione di un membro di un tipo, il tipo `Self` si riferisce a quel tipo. Nei membri di una dichiarazione di classe, `Self` può comparire solo come segue:

* Come tipo di ritorno di un metodo
* Come tipo di ritorno di un subscript di sola lettura
* Come tipo di una proprietà calcolata di sola lettura
* Nel corpo di un metodo

Per esempio, il codice seguente mostra un metodo di istanza `f` il cui tipo di ritorno è `Self`.

```swift
class Superclass {
    func f() -> Self { return self }
}
let x = Superclass()
print(type(of: x.f()))
// Stampa "Superclass".

class Subclass: Superclass { }
let y = Subclass()
print(type(of: y.f()))
// Stampa "Subclass".

let z: Superclass = Subclass()
print(type(of: z.f()))
// Stampa "Subclass".
```

L'ultima parte dell'esempio qui sopra mostra che `Self` si riferisce al tipo in fase di esecuzione `Subclass` del valore di `z`, non al tipo in fase di compilazione `Superclass` della variabile stessa.

All'interno di una dichiarazione di tipo annidata, il tipo `Self` si riferisce al tipo introdotto dalla dichiarazione di tipo più interna.

Il tipo `Self` si riferisce allo stesso tipo della funzione [`type(of:)`](https://developer.apple.com/documentation/swift/type\(of:\)) della libreria standard di Swift. Scrivere `Self.someStaticMember` per accedere a un membro del tipo corrente equivale a scrivere `type(of: self).someStaticMember`.

{% hint style="info" %}
**Grammatica di un tipo Self:**

*self-type* → **`Self`**
{% endhint %}

## Clausola di ereditarietà del tipo <a href="#clausola-di-ereditarieta-del-tipo" id="clausola-di-ereditarieta-del-tipo"></a>

Una *clausola di ereditarietà del tipo* serve a specificare da quale classe eredita un tipo con nome e a quali protocolli è conforme un tipo con nome. Una clausola di ereditarietà del tipo inizia con i due punti (`:`), seguiti da un elenco di identificatori di tipo.

I tipi classe possono ereditare da un'unica superclasse ed essere conformi a un numero qualsiasi di protocolli. Quando definisci una classe, il nome della superclasse deve comparire per primo nell'elenco degli identificatori di tipo, seguito da un numero qualsiasi di protocolli a cui la classe deve essere conforme. Se la classe non eredita da un'altra classe, l'elenco può invece iniziare con un protocollo. Per una discussione approfondita e diversi esempi di ereditarietà delle classi, vedi [Ereditarietà](/guida-al-linguaggio/ereditarieta.md).

Gli altri tipi con nome possono solo ereditare da un elenco di protocolli o essere conformi a esso. I tipi protocollo possono ereditare da un numero qualsiasi di altri protocolli. Quando un tipo protocollo eredita da altri protocolli, l'insieme dei requisiti di quegli altri protocolli viene aggregato, e qualsiasi tipo che eredita dal protocollo corrente deve essere conforme a tutti quei requisiti. Scrivere una tilde (`~`) davanti al nome di un protocollo in questo elenco sopprime una conformità implicita a quel protocollo, come descritto in [Conformità implicita a un protocollo](/guida-al-linguaggio/protocolli.md#conformita-implicita-a-un-protocollo).

Una clausola di ereditarietà del tipo nella definizione di un'enumerazione può essere un elenco di protocolli, oppure, nel caso di un'enumerazione che assegna valori grezzi ai suoi casi, un unico tipo con nome che specifica il tipo di quei valori grezzi. Per un esempio di definizione di un'enumerazione che usa una clausola di ereditarietà del tipo per specificare il tipo dei suoi valori grezzi, vedi [Valori grezzi](/guida-al-linguaggio/enumerazioni.md#valori-grezzi).

{% hint style="info" %}
**Grammatica di una clausola di ereditarietà del tipo:**

*type-inheritance-clause* → **`:`** *type-inheritance-list*\
*type-inheritance-list* → *attributes?* **`~`***?* *type-identifier* | *attributes?* **`~`***?* *type-identifier* **`,`** *type-inheritance-list*
{% endhint %}

## Inferenza di tipo <a href="#inferenza-di-tipo" id="inferenza-di-tipo"></a>

Swift usa ampiamente l'*inferenza di tipo*, che ti permette di omettere il tipo o parte del tipo di molte variabili ed espressioni del tuo codice. Per esempio, invece di scrivere `var x: Int = 0`, puoi scrivere `var x = 0`, omettendo completamente il tipo — il compilatore inferisce correttamente che `x` indica un valore di tipo `Int`. Analogamente, puoi omettere parte di un tipo quando il tipo completo può essere inferito dal contesto. Per esempio, se scrivi `let dict: Dictionary = ["A": 1]`, il compilatore inferisce che `dict` ha il tipo `Dictionary<String, Int>`.

In entrambi gli esempi qui sopra, le informazioni di tipo vengono passate verso l'alto, dalle foglie dell'albero dell'espressione alla sua radice. Cioè, il tipo di `x` in `var x: Int = 0` viene inferito verificando prima il tipo di `0` e poi passando questa informazione di tipo verso l'alto fino alla radice (la variabile `x`).

In Swift, le informazioni di tipo possono fluire anche nella direzione opposta — dalla radice verso le foglie. Nell'esempio seguente, per esempio, l'annotazione di tipo esplicita (`: Float`) sulla costante `eFloat` fa sì che il letterale numerico `2.71828` abbia un tipo inferito `Float` anziché `Double`.

```swift
let e = 2.71828 // Il tipo di e viene inferito come Double.
let eFloat: Float = 2.71828 // Il tipo di eFloat è Float.
```

L'inferenza di tipo in Swift opera a livello di una singola espressione o istruzione. Ciò significa che tutte le informazioni necessarie per inferire un tipo omesso o parte di un tipo in un'espressione devono essere accessibili a partire dal controllo dei tipi dell'espressione o di una delle sue sottoespressioni.
