> 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/generici.md).

# Generici (Generics)

Scrivi codice che funziona con più tipi e specifica i requisiti per quei tipi.

Il *codice generico* ti permette di scrivere funzioni e tipi flessibili e riutilizzabili che possono lavorare con qualsiasi tipo, nel rispetto dei requisiti che definisci. Puoi scrivere codice che evita le duplicazioni ed esprime la propria intenzione in modo chiaro e astratto.

I generici sono una delle funzionalità più potenti di Swift, e gran parte della libreria standard di Swift è costruita con codice generico. Anzi, hai usato i generici in tutta la *Guida al linguaggio*, anche se non te ne sei reso conto. Per esempio, i tipi `Array` e `Dictionary` di Swift sono entrambi collezioni generiche. Puoi creare un array che contiene valori `Int`, o un array che contiene valori `String`, o addirittura un array per qualsiasi altro tipo che si possa creare in Swift. Analogamente, puoi creare un dizionario per memorizzare valori di qualsiasi tipo specificato, e non ci sono limitazioni su quale possa essere quel tipo.

## Il problema che i generici risolvono <a href="#il-problema-che-i-generici-risolvono" id="il-problema-che-i-generici-risolvono"></a>

Ecco una funzione standard, non generica, chiamata `swapTwoInts(_:_:)`, che scambia due valori `Int`:

```swift
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
```

Questa funzione si avvale dei parametri in-out per scambiare i valori di `a` e `b`, come descritto in [Parametri in-out](/guida-al-linguaggio/funzioni.md#parametri-in-out).

La funzione `swapTwoInts(_:_:)` scambia il valore originale di `b` in `a`, e il valore originale di `a` in `b`. Puoi chiamare questa funzione per scambiare i valori di due variabili `Int`:

```swift
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Stampa "someInt is now 107, and anotherInt is now 3".
```

La funzione `swapTwoInts(_:_:)` è utile, ma può essere usata solo con valori `Int`. Se vuoi scambiare due valori `String`, o due valori `Double`, devi scrivere altre funzioni, come le funzioni `swapTwoStrings(_:_:)` e `swapTwoDoubles(_:_:)` mostrate di seguito:

```swift
func swapTwoStrings(_ a: inout String, _ b: inout String) {
    let temporaryA = a
    a = b
    b = temporaryA
}

func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
    let temporaryA = a
    a = b
    b = temporaryA
}
```

Potresti aver notato che i corpi delle funzioni `swapTwoInts(_:_:)`, `swapTwoStrings(_:_:)` e `swapTwoDoubles(_:_:)` sono identici. L'unica differenza è il tipo dei valori che accettano (`Int`, `String` e `Double`).

È più utile, e considerevolmente più flessibile, scrivere un'unica funzione che scambi due valori di *qualsiasi* tipo. Il codice generico ti permette di scrivere una funzione del genere. (Una versione generica di queste funzioni è definita più avanti.)

{% hint style="info" %}
**Nota:** In tutte e tre le funzioni, i tipi di `a` e `b` devono essere uguali. Se `a` e `b` non sono dello stesso tipo, non è possibile scambiarne i valori. Swift è un linguaggio sicuro rispetto ai tipi, e non consente (per esempio) a una variabile di tipo `String` e a una variabile di tipo `Double` di scambiarsi i valori. Tentare di farlo produce un errore in fase di compilazione.
{% endhint %}

## Funzioni generiche <a href="#funzioni-generiche" id="funzioni-generiche"></a>

Le *funzioni generiche* possono lavorare con qualsiasi tipo. Ecco una versione generica della funzione `swapTwoInts(_:_:)` vista sopra, chiamata `swapTwoValues(_:_:)`:

```swift
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}
```

Il corpo della funzione `swapTwoValues(_:_:)` è identico al corpo della funzione `swapTwoInts(_:_:)`. Tuttavia, la prima riga di `swapTwoValues(_:_:)` è leggermente diversa da quella di `swapTwoInts(_:_:)`. Ecco un confronto tra le prime righe:

```swift
func swapTwoInts(_ a: inout Int, _ b: inout Int)
func swapTwoValues<T>(_ a: inout T, _ b: inout T)
```

La versione generica della funzione usa un nome di tipo *segnaposto* (chiamato `T`, in questo caso) invece di un nome di tipo *effettivo* (come `Int`, `String` o `Double`). Il nome di tipo segnaposto non dice nulla su che cosa debba essere `T`, ma *dice* che sia `a` sia `b` devono essere dello stesso tipo `T`, qualunque cosa `T` rappresenti. Il tipo effettivo da usare al posto di `T` viene determinato ogni volta che viene chiamata la funzione `swapTwoValues(_:_:)`.

L'altra differenza tra una funzione generica e una funzione non generica è che il nome della funzione generica (`swapTwoValues(_:_:)`) è seguito dal nome di tipo segnaposto (`T`) tra parentesi angolari (`<T>`). Le parentesi dicono a Swift che `T` è un nome di tipo segnaposto all'interno della definizione della funzione `swapTwoValues(_:_:)`. Poiché `T` è un segnaposto, Swift non cerca un tipo effettivo chiamato `T`.

La funzione `swapTwoValues(_:_:)` può ora essere chiamata nello stesso modo di `swapTwoInts`, tranne per il fatto che le si possono passare due valori di *qualsiasi* tipo, purché entrambi i valori siano dello stesso tipo tra loro. Ogni volta che `swapTwoValues(_:_:)` viene chiamata, il tipo da usare per `T` viene inferito dai tipi dei valori passati alla funzione.

Nei due esempi seguenti, `T` viene inferito rispettivamente come `Int` e come `String`:

```swift
var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
// someInt ora vale 107, e anotherInt ora vale 3

var someString = "hello"
var anotherString = "world"
swapTwoValues(&someString, &anotherString)
// someString ora è "world", e anotherString ora è "hello"
```

{% hint style="info" %}
**Nota:** La funzione `swapTwoValues(_:_:)` definita sopra è ispirata a una funzione generica chiamata `swap`, che fa parte della libreria standard di Swift, ed è resa automaticamente disponibile per l'uso nelle tue app. Se hai bisogno del comportamento della funzione `swapTwoValues(_:_:)` nel tuo codice, puoi usare la funzione `swap(_:_:)` già esistente in Swift anziché fornire una tua implementazione.
{% endhint %}

## Parametri di tipo <a href="#parametri-di-tipo" id="parametri-di-tipo"></a>

Nell'esempio `swapTwoValues(_:_:)` qui sopra, il tipo segnaposto `T` è un esempio di *parametro di tipo*. I parametri di tipo specificano e danno un nome a un tipo segnaposto, e si scrivono subito dopo il nome della funzione, tra una coppia di parentesi angolari corrispondenti (come `<T>`).

Una volta specificato un parametro di tipo, puoi usarlo per definire il tipo dei parametri di una funzione (come i parametri `a` e `b` della funzione `swapTwoValues(_:_:)`), o come tipo di ritorno della funzione, o come annotazione di tipo all'interno del corpo della funzione. In ciascun caso, il parametro di tipo viene sostituito con un tipo *effettivo* ogni volta che la funzione viene chiamata. (Nell'esempio `swapTwoValues(_:_:)` qui sopra, `T` è stato sostituito con `Int` la prima volta che la funzione è stata chiamata, ed è stato sostituito con `String` la seconda volta.)

Puoi fornire più di un parametro di tipo scrivendo più nomi di parametri di tipo tra le parentesi angolari, separati da virgole.

## Denominare i parametri di tipo <a href="#denominare-i-parametri-di-tipo" id="denominare-i-parametri-di-tipo"></a>

Nella maggior parte dei casi, i parametri di tipo hanno nomi descrittivi, come `Key` e `Value` in `Dictionary<Key, Value>` ed `Element` in `Array<Element>`, che informano il lettore sulla relazione tra il parametro di tipo e il tipo o la funzione generica in cui è usato. Tuttavia, quando tra loro non c'è una relazione significativa, è tradizione denominarli con singole lettere come `T`, `U` e `V`, come `T` nella funzione `swapTwoValues(_:_:)` qui sopra.

Usa nomi in upper camel case per i parametri di tipo, come `T` e `MyTypeParameter`, per indicare che sono un segnaposto per un *tipo*, non per un valore.

{% hint style="info" %}
**Nota:** Se non hai bisogno di dare un nome a un parametro di tipo e i suoi vincoli di tipo generici sono semplici, esiste una sintassi alternativa e leggera che puoi usare, come descritto in [Tipi parametro opachi](/guida-al-linguaggio/tipi-opachi-e-tipi-protocollo-boxed.md#tipi-parametro-opachi).
{% endhint %}

## Tipi generici <a href="#tipi-generici" id="tipi-generici"></a>

Oltre alle funzioni generiche, Swift ti permette di definire i tuoi *tipi generici*. Si tratta di classi, strutture ed enumerazioni personalizzate che possono lavorare con *qualsiasi* tipo, in modo simile ad `Array` e `Dictionary`.

Questa sezione ti mostra come scrivere un tipo collezione generico chiamato `Stack`. Uno stack (pila) è un insieme ordinato di valori, simile a un array, ma con un insieme di operazioni più limitato rispetto al tipo `Array` di Swift. Un array permette di inserire e rimuovere nuovi elementi in qualsiasi posizione dell'array. Uno stack, invece, permette di aggiungere nuovi elementi solo alla fine della collezione (operazione nota come *push* di un nuovo valore sullo stack). Analogamente, uno stack permette di rimuovere elementi solo dalla fine della collezione (operazione nota come *pop* di un valore dallo stack).

{% hint style="info" %}
**Nota:** Il concetto di stack è usato dalla classe `UINavigationController` per modellare i view controller nella sua gerarchia di navigazione. Chiami il metodo `pushViewController(_:animated:)` della classe `UINavigationController` per aggiungere (o fare il push di) un view controller allo stack di navigazione, e il suo metodo `popViewControllerAnimated(_:)` per rimuovere (o fare il pop di) un view controller dallo stack di navigazione. Uno stack è un modello di collezione utile ogni volta che hai bisogno di un approccio rigoroso “last in, first out” (l'ultimo a entrare è il primo a uscire) per gestire una collezione.
{% endhint %}

L'illustrazione seguente mostra il comportamento di push e pop di uno stack:

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

1. Al momento ci sono tre valori sullo stack.
2. Un quarto valore viene aggiunto (push) in cima allo stack.
3. Lo stack ora contiene quattro valori, con il più recente in cima.
4. L'elemento in cima allo stack viene rimosso (pop).
5. Dopo il pop di un valore, lo stack contiene di nuovo tre valori.

Ecco come scrivere una versione non generica di uno stack, in questo caso per uno stack di valori `Int`:

```swift
struct IntStack {
    var items: [Int] = []
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
}
```

Questa struttura usa una proprietà `Array` chiamata `items` per memorizzare i valori dello stack. `Stack` fornisce due metodi, `push` e `pop`, per aggiungere e rimuovere valori dallo stack. Questi metodi sono contrassegnati come `mutating`, perché devono modificare (o *mutare*) l'array `items` della struttura.

Il tipo `IntStack` mostrato sopra, tuttavia, può essere usato solo con valori `Int`. Sarebbe molto più utile definire una struttura `Stack` *generica*, in grado di gestire uno stack di valori di *qualsiasi* tipo.

Ecco una versione generica dello stesso codice:

```swift
struct Stack<Element> {
    var items: [Element] = []
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}
```

Nota come la versione generica di `Stack` sia essenzialmente uguale alla versione non generica, ma con un parametro di tipo chiamato `Element` invece di un tipo effettivo `Int`. Questo parametro di tipo è scritto all'interno di una coppia di parentesi angolari (`<Element>`) subito dopo il nome della struttura.

`Element` definisce un nome segnaposto per un tipo che verrà fornito in seguito. Si può fare riferimento a questo tipo futuro come `Element` ovunque all'interno della definizione della struttura. In questo caso, `Element` è usato come segnaposto in tre punti:

* Per creare una proprietà chiamata `items`, che viene inizializzata con un array vuoto di valori di tipo `Element`
* Per specificare che il metodo `push(_:)` ha un unico parametro chiamato `item`, che deve essere di tipo `Element`
* Per specificare che il valore restituito dal metodo `pop()` sarà un valore di tipo `Element`

Poiché è un tipo generico, `Stack` può essere usato per creare uno stack di *qualsiasi* tipo valido in Swift, in modo simile ad `Array` e `Dictionary`.

Crei una nuova istanza di `Stack` scrivendo il tipo da memorizzare nello stack tra parentesi angolari. Per esempio, per creare un nuovo stack di stringhe, scrivi `Stack<String>()`:

```swift
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// lo stack ora contiene 4 stringhe
```

Ecco come appare `stackOfStrings` dopo aver aggiunto questi quattro valori allo stack:

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

Rimuovere un valore dallo stack rimuove e restituisce il valore in cima, `"cuatro"`:

```swift
let fromTheTop = stackOfStrings.pop()
// fromTheTop è uguale a "cuatro", e lo stack ora contiene 3 stringhe
```

Ecco come appare lo stack dopo aver rimosso il valore in cima:

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

## Estendere un tipo generico <a href="#estendere-un-tipo-generico" id="estendere-un-tipo-generico"></a>

Quando estendi un tipo generico, non fornisci un elenco di parametri di tipo come parte della definizione dell'estensione. Invece, l'elenco dei parametri di tipo della definizione del tipo *originale* è disponibile all'interno del corpo dell'estensione, e i nomi originali dei parametri di tipo vengono usati per riferirsi ai parametri di tipo della definizione originale.

L'esempio seguente estende il tipo generico `Stack` per aggiungere una proprietà calcolata di sola lettura chiamata `topItem`, che restituisce l'elemento in cima allo stack senza rimuoverlo dallo stack:

```swift
extension Stack {
    var topItem: Element? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}
```

La proprietà `topItem` restituisce un valore opzionale di tipo `Element`. Se lo stack è vuoto, `topItem` restituisce `nil`; se lo stack non è vuoto, `topItem` restituisce l'ultimo elemento dell'array `items`.

Nota che questa estensione non definisce un elenco di parametri di tipo. Invece, il nome del parametro di tipo esistente del tipo `Stack`, `Element`, viene usato all'interno dell'estensione per indicare il tipo opzionale della proprietà calcolata `topItem`.

La proprietà calcolata `topItem` può ora essere usata con qualsiasi istanza di `Stack` per accedere al suo elemento in cima e interrogarlo senza rimuoverlo.

```swift
if let topItem = stackOfStrings.topItem {
    print("The top item on the stack is \(topItem).")
}
// Stampa "The top item on the stack is tres."
```

Le estensioni di un tipo generico possono anche includere requisiti che le istanze del tipo esteso devono soddisfare per ottenere la nuova funzionalità, come discusso più avanti in [Estensioni con una clausola where generica](/guida-al-linguaggio/generici.md#estensioni-con-una-clausola-where-generica).

## Vincoli di tipo <a href="#vincoli-di-tipo" id="vincoli-di-tipo"></a>

La funzione `swapTwoValues(_:_:)` e il tipo `Stack` possono lavorare con qualsiasi tipo. Tuttavia, a volte è utile imporre certi *vincoli di tipo* sui tipi che possono essere usati con funzioni generiche e tipi generici. I vincoli di tipo specificano che un parametro di tipo deve ereditare da una specifica classe, oppure essere conforme a un particolare protocollo o a una composizione di protocolli.

Per esempio, il tipo `Dictionary` di Swift pone una limitazione sui tipi che possono essere usati come chiavi di un dizionario. Come descritto in [Dizionari](/guida-al-linguaggio/tipi-collezione.md#dizionari), il tipo delle chiavi di un dizionario deve essere *hashable*. Cioè, deve fornire un modo per rendersi rappresentabile in modo univoco. `Dictionary` ha bisogno che le sue chiavi siano hashable per poter verificare se contiene già un valore per una particolare chiave. Senza questo requisito, `Dictionary` non potrebbe stabilire se debba inserire o sostituire un valore per una particolare chiave, né sarebbe in grado di trovare un valore per una data chiave già presente nel dizionario.

Questo requisito è imposto da un vincolo di tipo sul tipo della chiave di `Dictionary`, che specifica che il tipo della chiave deve essere conforme al protocollo `Hashable`, un protocollo speciale definito nella libreria standard di Swift. Tutti i tipi di base di Swift (come `String`, `Int`, `Double` e `Bool`) sono hashable per impostazione predefinita. Per informazioni su come rendere i tuoi tipi personalizzati conformi al protocollo `Hashable`, vedi [Conforming to the Hashable Protocol](https://developer.apple.com/documentation/swift/hashable#Conforming-to-the-Hashable-Protocol).

Puoi definire i tuoi vincoli di tipo quando crei tipi generici personalizzati, e questi vincoli forniscono gran parte della potenza della programmazione generica. Concetti astratti come `Hashable` caratterizzano i tipi in termini delle loro caratteristiche concettuali, anziché del loro tipo concreto.

### Sintassi dei vincoli di tipo <a href="#sintassi-dei-vincoli-di-tipo" id="sintassi-dei-vincoli-di-tipo"></a>

Scrivi i vincoli di tipo collocando un singolo vincolo di classe o di protocollo dopo il nome di un parametro di tipo, separato da due punti, come parte dell'elenco dei parametri di tipo. La sintassi di base dei vincoli di tipo su una funzione generica è mostrata di seguito (anche se la sintassi è la stessa per i tipi generici):

```swift
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // qui va il corpo della funzione
}
```

L'ipotetica funzione qui sopra ha due parametri di tipo. Il primo parametro di tipo, `T`, ha un vincolo di tipo che richiede che `T` sia una sottoclasse di `SomeClass`. Il secondo parametro di tipo, `U`, ha un vincolo di tipo che richiede che `U` sia conforme al protocollo `SomeProtocol`.

### I vincoli di tipo in azione <a href="#i-vincoli-di-tipo-in-azione" id="i-vincoli-di-tipo-in-azione"></a>

Ecco una funzione non generica chiamata `findIndex(ofString:in:)`, a cui vengono dati un valore `String` da cercare e un array di valori `String` in cui cercarlo. La funzione `findIndex(ofString:in:)` restituisce un valore `Int` opzionale, che sarà l'indice della prima stringa corrispondente nell'array, se viene trovata, oppure `nil` se la stringa non può essere trovata:

```swift
func findIndex(ofString valueToFind: String, in array: [String]) -> Int? {
    for (index, value) in array.enumerated() {
        if value == valueToFind {
            return index
        }
    }
    return nil
}
```

La funzione `findIndex(ofString:in:)` può essere usata per trovare un valore stringa in un array di stringhe:

```swift
let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
if let foundIndex = findIndex(ofString: "llama", in: strings) {
    print("The index of llama is \(foundIndex)")
}
// Stampa "The index of llama is 2".
```

Il principio di trovare l'indice di un valore in un array, però, non è utile solo per le stringhe. Puoi scrivere la stessa funzionalità come funzione generica sostituendo ogni riferimento alle stringhe con valori di un qualche tipo `T`.

Ecco come potresti aspettarti che venga scritta una versione generica di `findIndex(ofString:in:)`, chiamata `findIndex(of:in:)`. Nota che il tipo di ritorno di questa funzione è ancora `Int?`, perché la funzione restituisce un numero di indice opzionale, non un valore opzionale dell'array. Attenzione, però — questa funzione non compila, per ragioni spiegate dopo l'esempio:

```swift
func findIndex<T>(of valueToFind: T, in array:[T]) -> Int? {
    for (index, value) in array.enumerated() {
        if value == valueToFind {
            return index
        }
    }
    return nil
}
```

Questa funzione non compila così come è scritta qui sopra. Il problema risiede nel controllo di uguaglianza, “`if value == valueToFind`”. Non tutti i tipi in Swift possono essere confrontati con l'operatore uguale a (`==`). Se crei la tua classe o struttura per rappresentare un modello di dati complesso, per esempio, allora il significato di “uguale a” per quella classe o struttura non è qualcosa che Swift può indovinare per te. Per questo motivo, non è possibile garantire che questo codice funzioni per *ogni* possibile tipo `T`, e viene segnalato un errore appropriato quando provi a compilare il codice.

Non tutto è perduto, però. La libreria standard di Swift definisce un protocollo chiamato `Equatable`, che richiede a qualsiasi tipo conforme di implementare l'operatore uguale a (`==`) e l'operatore diverso da (`!=`) per confrontare due valori qualsiasi di quel tipo. Tutti i tipi standard di Swift supportano automaticamente il protocollo `Equatable`.

Qualsiasi tipo che sia `Equatable` può essere usato in modo sicuro con la funzione `findIndex(of:in:)`, perché è garantito che supporti l'operatore uguale a. Per esprimere questo fatto, scrivi un vincolo di tipo `Equatable` come parte della definizione del parametro di tipo quando definisci la funzione:

```swift
func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
    for (index, value) in array.enumerated() {
        if value == valueToFind {
            return index
        }
    }
    return nil
}
```

L'unico parametro di tipo di `findIndex(of:in:)` si scrive `T: Equatable`, che significa “qualsiasi tipo `T` conforme al protocollo `Equatable`”.

La funzione `findIndex(of:in:)` ora compila correttamente e può essere usata con qualsiasi tipo `Equatable`, come `Double` o `String`:

```swift
let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25])
// doubleIndex è un Int opzionale privo di valore, perché 9.3 non è nell'array
let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"])
// stringIndex è un Int opzionale contenente il valore 2
```

## Tipi associati <a href="#tipi-associati" id="tipi-associati"></a>

Quando definisci un protocollo, a volte è utile dichiarare uno o più tipi associati come parte della definizione del protocollo. Un *tipo associato* dà un nome segnaposto a un tipo usato come parte del protocollo. Il tipo effettivo da usare per quel tipo associato non viene specificato finché il protocollo non viene adottato. I tipi associati si specificano con la parola chiave `associatedtype`.

### I tipi associati in azione <a href="#i-tipi-associati-in-azione" id="i-tipi-associati-in-azione"></a>

Ecco un esempio di un protocollo chiamato `Container`, che dichiara un tipo associato chiamato `Item`:

```swift
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}
```

Il protocollo `Container` definisce tre capacità richieste che qualsiasi contenitore deve fornire:

* Deve essere possibile aggiungere un nuovo elemento al contenitore con un metodo `append(_:)`.
* Deve essere possibile accedere al numero di elementi del contenitore tramite una proprietà `count` che restituisce un valore `Int`.
* Deve essere possibile recuperare ciascun elemento del contenitore con un subscript che accetta un valore di indice `Int`.

Questo protocollo non specifica come debbano essere memorizzati gli elementi del contenitore né di che tipo possano essere. Il protocollo specifica soltanto le tre porzioni di funzionalità che qualsiasi tipo deve fornire per essere considerato un `Container`. Un tipo conforme può fornire funzionalità aggiuntive, purché soddisfi questi tre requisiti.

Qualsiasi tipo conforme al protocollo `Container` deve essere in grado di specificare il tipo dei valori che memorizza. Nello specifico, deve garantire che al contenitore vengano aggiunti solo elementi del tipo giusto, e deve essere chiaro riguardo al tipo degli elementi restituiti dal suo subscript.

Per definire questi requisiti, il protocollo `Container` ha bisogno di un modo per riferirsi al tipo degli elementi che un contenitore conterrà, senza sapere quale sia quel tipo per uno specifico contenitore. Il protocollo `Container` deve specificare che qualsiasi valore passato al metodo `append(_:)` deve avere lo stesso tipo degli elementi del contenitore, e che il valore restituito dal subscript del contenitore sarà dello stesso tipo degli elementi del contenitore.

Per ottenere questo, il protocollo `Container` dichiara un tipo associato chiamato `Item`, scritto come `associatedtype Item`. Il protocollo non definisce che cosa sia `Item` — questa informazione è lasciata a qualsiasi tipo conforme. Ciononostante, l'alias `Item` fornisce un modo per riferirsi al tipo degli elementi di un `Container`, e per definire un tipo da usare con il metodo `append(_:)` e con il subscript, per garantire che il comportamento atteso di qualsiasi `Container` venga rispettato.

Ecco una versione del tipo non generico `IntStack` visto in [Tipi generici](/guida-al-linguaggio/generici.md#tipi-generici) sopra, adattata per essere conforme al protocollo `Container`:

```swift
struct IntStack: Container {
    // implementazione originale di IntStack
    var items: [Int] = []
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    // conformità al protocollo Container
    typealias Item = Int
    mutating func append(_ item: Int) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
}
```

Il tipo `IntStack` implementa tutti e tre i requisiti del protocollo `Container`, e in ciascun caso racchiude parte della funzionalità esistente del tipo `IntStack` per soddisfare questi requisiti.

Inoltre, `IntStack` specifica che, per questa implementazione di `Container`, l'`Item` appropriato da usare è un tipo `Int`. La definizione `typealias Item = Int` trasforma il tipo astratto `Item` in un tipo concreto `Int` per questa implementazione del protocollo `Container`.

Grazie all'inferenza di tipo di Swift, in realtà non hai bisogno di dichiarare un `Item` concreto di tipo `Int` come parte della definizione di `IntStack`. Poiché `IntStack` è conforme a tutti i requisiti del protocollo `Container`, Swift può inferire l'`Item` appropriato da usare, semplicemente osservando il tipo del parametro `item` del metodo `append(_:)` e il tipo di ritorno del subscript. Infatti, se elimini la riga `typealias Item = Int` dal codice qui sopra, tutto funziona comunque, perché è chiaro quale tipo debba essere usato per `Item`.

Puoi anche rendere il tipo generico `Stack` conforme al protocollo `Container`:

```swift
struct Stack<Element>: Container {
    // implementazione originale di Stack<Element>
    var items: [Element] = []
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
    // conformità al protocollo Container
    mutating func append(_ item: Element) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Element {
        return items[i]
    }
}
```

Questa volta, il parametro di tipo `Element` viene usato come tipo del parametro `item` del metodo `append(_:)` e come tipo di ritorno del subscript. Swift può quindi inferire che `Element` è il tipo appropriato da usare come `Item` per questo particolare contenitore.

### Estendere un tipo esistente per specificare un tipo associato <a href="#estendere-un-tipo-esistente-per-specificare-un-tipo-associato" id="estendere-un-tipo-esistente-per-specificare-un-tipo-associato"></a>

Puoi estendere un tipo esistente per aggiungere la conformità a un protocollo, come descritto in [Aggiungere la conformità a un protocollo con un'estensione](/guida-al-linguaggio/protocolli.md#aggiungere-la-conformita-a-un-protocollo-con-unestensione). Questo vale anche per un protocollo con un tipo associato.

Il tipo `Array` di Swift fornisce già un metodo `append(_:)`, una proprietà `count` e un subscript con un indice `Int` per recuperare i suoi elementi. Queste tre capacità corrispondono ai requisiti del protocollo `Container`. Ciò significa che puoi estendere `Array` affinché sia conforme al protocollo `Container` semplicemente dichiarando che `Array` adotta il protocollo. Lo fai con un'estensione vuota, come descritto in [Dichiarare l'adozione di un protocollo con un'estensione](/guida-al-linguaggio/protocolli.md#dichiarare-ladozione-di-un-protocollo-con-unestensione):

```swift
extension Array: Container {}
```

Il metodo `append(_:)` e il subscript già esistenti di Array permettono a Swift di inferire il tipo appropriato da usare per `Item`, proprio come per il tipo generico `Stack` visto sopra. Dopo aver definito questa estensione, puoi usare qualsiasi `Array` come `Container`.

### Aggiungere vincoli a un tipo associato <a href="#aggiungere-vincoli-a-un-tipo-associato" id="aggiungere-vincoli-a-un-tipo-associato"></a>

Puoi aggiungere vincoli di tipo a un tipo associato in un protocollo per richiedere che i tipi conformi soddisfino quei vincoli. Per esempio, il codice seguente definisce una versione di `Container` che richiede che gli elementi del contenitore siano equatable.

```swift
protocol Container {
    associatedtype Item: Equatable
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}
```

Per essere conforme a questa versione di `Container`, il tipo `Item` del contenitore deve essere conforme al protocollo `Equatable`.

### Usare un protocollo nei vincoli del suo tipo associato <a href="#usare-un-protocollo-nei-vincoli-del-suo-tipo-associato" id="usare-un-protocollo-nei-vincoli-del-suo-tipo-associato"></a>

Un protocollo può comparire come parte dei propri requisiti. Per esempio, ecco un protocollo che perfeziona il protocollo `Container`, aggiungendo il requisito di un metodo `suffix(_:)`. Il metodo `suffix(_:)` restituisce un dato numero di elementi dalla fine del contenitore, memorizzandoli in un'istanza del tipo `Suffix`.

```swift
protocol SuffixableContainer: Container {
    associatedtype Suffix: SuffixableContainer where Suffix.Item == Item
    func suffix(_ size: Int) -> Suffix
}
```

In questo protocollo, `Suffix` è un tipo associato, come il tipo `Item` nell'esempio `Container` visto sopra. `Suffix` ha due vincoli: deve essere conforme al protocollo `SuffixableContainer` (il protocollo che si sta definendo), e il suo tipo `Item` deve essere lo stesso del tipo `Item` del contenitore. Il vincolo su `Item` è una clausola `where` generica, discussa più avanti in [Tipi associati con una clausola where generica](/guida-al-linguaggio/generici.md#tipi-associati-con-una-clausola-where-generica).

Ecco un'estensione del tipo `Stack` visto in [Tipi generici](/guida-al-linguaggio/generici.md#tipi-generici) sopra che aggiunge la conformità al protocollo `SuffixableContainer`:

```swift
extension Stack: SuffixableContainer {
    func suffix(_ size: Int) -> Stack {
        var result = Stack()
        for index in (count-size)..<count {
            result.append(self[index])
        }
        return result
    }
    // Si inferisce che Suffix è Stack.
}
var stackOfInts = Stack<Int>()
stackOfInts.append(10)
stackOfInts.append(20)
stackOfInts.append(30)
let suffix = stackOfInts.suffix(2)
// suffix contiene 20 e 30
```

Nell'esempio qui sopra, il tipo associato `Suffix` di `Stack` è anch'esso `Stack`, quindi l'operazione di suffisso su `Stack` restituisce un altro `Stack`. In alternativa, un tipo conforme a `SuffixableContainer` può avere un tipo `Suffix` diverso da sé stesso — il che significa che l'operazione di suffisso può restituire un tipo diverso. Per esempio, ecco un'estensione del tipo non generico `IntStack` che aggiunge la conformità a `SuffixableContainer`, usando `Stack<Int>` come tipo del suffisso invece di `IntStack`:

```swift
extension IntStack: SuffixableContainer {
    func suffix(_ size: Int) -> Stack<Int> {
        var result = Stack<Int>()
        for index in (count-size)..<count {
            result.append(self[index])
        }
        return result
    }
    // Si inferisce che Suffix è Stack<Int>.
}
```

## Clausole where generiche <a href="#clausole-where-generiche" id="clausole-where-generiche"></a>

I vincoli di tipo, come descritti in [Vincoli di tipo](/guida-al-linguaggio/generici.md#vincoli-di-tipo), ti permettono di definire requisiti sui parametri di tipo associati a una funzione, un subscript o un tipo generico.

Può essere utile anche definire requisiti per i tipi associati. Lo fai definendo una *clausola where generica*. Una clausola `where` generica ti permette di richiedere che un tipo associato sia conforme a un certo protocollo, o che certi parametri di tipo e tipi associati siano uguali. Una clausola `where` generica inizia con la parola chiave `where`, seguita da vincoli per i tipi associati o da relazioni di uguaglianza tra tipi e tipi associati. Scrivi una clausola `where` generica subito prima della parentesi graffa di apertura del corpo di un tipo o di una funzione.

L'esempio seguente definisce una funzione generica chiamata `allItemsMatch`, che verifica se due istanze di `Container` contengono gli stessi elementi nello stesso ordine. La funzione restituisce un valore booleano `true` se tutti gli elementi corrispondono e un valore `false` in caso contrario.

I due contenitori da verificare non devono essere necessariamente dello stesso tipo di contenitore (anche se possono esserlo), ma devono contenere lo stesso tipo di elementi. Questo requisito è espresso tramite una combinazione di vincoli di tipo e di una clausola `where` generica:

```swift
func allItemsMatch<C1: Container, C2: Container>
        (_ someContainer: C1, _ anotherContainer: C2) -> Bool
        where C1.Item == C2.Item, C1.Item: Equatable {

    // Verifica che entrambi i contenitori contengano lo stesso numero di elementi.
    if someContainer.count != anotherContainer.count {
        return false
    }

    // Verifica ogni coppia di elementi per vedere se sono equivalenti.
    for i in 0..<someContainer.count {
        if someContainer[i] != anotherContainer[i] {
            return false
        }
    }

    // Tutti gli elementi corrispondono, quindi restituisci true.
    return true
}
```

Questa funzione accetta due argomenti chiamati `someContainer` e `anotherContainer`. L'argomento `someContainer` è di tipo `C1`, e l'argomento `anotherContainer` è di tipo `C2`. Sia `C1` sia `C2` sono parametri di tipo per due tipi contenitore da determinare quando la funzione viene chiamata.

Sui due parametri di tipo della funzione sono imposti i requisiti seguenti:

* `C1` deve essere conforme al protocollo `Container` (scritto come `C1: Container`).
* Anche `C2` deve essere conforme al protocollo `Container` (scritto come `C2: Container`).
* L'`Item` di `C1` deve essere lo stesso dell'`Item` di `C2` (scritto come `C1.Item == C2.Item`).
* L'`Item` di `C1` deve essere conforme al protocollo `Equatable` (scritto come `C1.Item: Equatable`).

Il primo e il secondo requisito sono definiti nell'elenco dei parametri di tipo della funzione, e il terzo e il quarto requisito sono definiti nella clausola `where` generica della funzione.

Questi requisiti significano che:

* `someContainer` è un contenitore di tipo `C1`.
* `anotherContainer` è un contenitore di tipo `C2`.
* `someContainer` e `anotherContainer` contengono lo stesso tipo di elementi.
* Gli elementi di `someContainer` possono essere confrontati con l'operatore diverso da (`!=`) per vedere se sono diversi tra loro.

Il terzo e il quarto requisito combinati significano che *anche* gli elementi di `anotherContainer` possono essere confrontati con l'operatore `!=`, perché sono esattamente dello stesso tipo degli elementi di `someContainer`.

Questi requisiti permettono alla funzione `allItemsMatch(_:_:)` di confrontare i due contenitori, anche se sono di un tipo di contenitore diverso.

La funzione `allItemsMatch(_:_:)` inizia verificando che entrambi i contenitori contengano lo stesso numero di elementi. Se contengono un numero diverso di elementi, non c'è modo che possano corrispondere, e la funzione restituisce `false`.

Dopo aver effettuato questa verifica, la funzione itera su tutti gli elementi di `someContainer` con un ciclo `for`-`in` e l'operatore di intervallo semiaperto (`..<`). Per ciascun elemento, la funzione verifica se l'elemento di `someContainer` non è uguale all'elemento corrispondente di `anotherContainer`. Se i due elementi non sono uguali, allora i due contenitori non corrispondono, e la funzione restituisce `false`.

Se il ciclo termina senza trovare una discrepanza, i due contenitori corrispondono, e la funzione restituisce `true`.

Ecco come appare la funzione `allItemsMatch(_:_:)` in azione:

```swift
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")

var arrayOfStrings = ["uno", "dos", "tres"]

if allItemsMatch(stackOfStrings, arrayOfStrings) {
    print("All items match.")
} else {
    print("Not all items match.")
}
// Stampa "All items match."
```

L'esempio qui sopra crea un'istanza di `Stack` per memorizzare valori `String`, e aggiunge tre stringhe allo stack. L'esempio crea anche un'istanza di `Array` inizializzata con un letterale array contenente le stesse tre stringhe dello stack. Anche se lo stack e l'array sono di tipo diverso, sono entrambi conformi al protocollo `Container`, ed entrambi contengono lo stesso tipo di valori. Puoi quindi chiamare la funzione `allItemsMatch(_:_:)` con questi due contenitori come argomenti. Nell'esempio qui sopra, la funzione `allItemsMatch(_:_:)` riporta correttamente che tutti gli elementi dei due contenitori corrispondono.

## Estensioni con una clausola where generica <a href="#estensioni-con-una-clausola-where-generica" id="estensioni-con-una-clausola-where-generica"></a>

Puoi usare una clausola `where` generica anche come parte di un'estensione. L'esempio seguente estende la struttura generica `Stack` degli esempi precedenti per aggiungere un metodo `isTop(_:)`.

```swift
extension Stack where Element: Equatable {
    func isTop(_ item: Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        return topItem == item
    }
}
```

Questo nuovo metodo `isTop(_:)` verifica innanzitutto che lo stack non sia vuoto, e poi confronta l'elemento dato con l'elemento più in alto dello stack. Se provassi a farlo senza una clausola `where` generica, avresti un problema: l'implementazione di `isTop(_:)` usa l'operatore `==`, ma la definizione di `Stack` non richiede che i suoi elementi siano equatable, quindi usare l'operatore `==` produce un errore in fase di compilazione. Usare una clausola `where` generica ti permette di aggiungere un nuovo requisito all'estensione, in modo che l'estensione aggiunga il metodo `isTop(_:)` solo quando gli elementi dello stack sono equatable.

Ecco come appare il metodo `isTop(_:)` in azione:

```swift
if stackOfStrings.isTop("tres") {
    print("Top element is tres.")
} else {
    print("Top element is something else.")
}
// Stampa "Top element is tres."
```

Se provi a chiamare il metodo `isTop(_:)` su uno stack i cui elementi non sono equatable, otterrai un errore in fase di compilazione.

```swift
struct NotEquatable { }
var notEquatableStack = Stack<NotEquatable>()
let notEquatableValue = NotEquatable()
notEquatableStack.push(notEquatableValue)
notEquatableStack.isTop(notEquatableValue)  // Errore
```

Puoi usare una clausola `where` generica con le estensioni di un protocollo. L'esempio seguente estende il protocollo `Container` degli esempi precedenti per aggiungere un metodo `startsWith(_:)`.

```swift
extension Container where Item: Equatable {
    func startsWith(_ item: Item) -> Bool {
        return count >= 1 && self[0] == item
    }
}
```

Il metodo `startsWith(_:)` si assicura innanzitutto che il contenitore abbia almeno un elemento, e poi verifica se il primo elemento del contenitore corrisponde all'elemento dato. Questo nuovo metodo `startsWith(_:)` può essere usato con qualsiasi tipo conforme al protocollo `Container`, compresi gli stack e gli array usati sopra, purché gli elementi del contenitore siano equatable.

```swift
if [9, 9, 9].startsWith(42) {
    print("Starts with 42.")
} else {
    print("Starts with something else.")
}
// Stampa "Starts with something else."
```

La clausola `where` generica dell'esempio qui sopra richiede che `Item` sia conforme a un protocollo, ma puoi anche scrivere clausole `where` generiche che richiedono che `Item` sia un tipo specifico. Per esempio:

```swift
extension Container where Item == Double {
    func average() -> Double {
        var sum = 0.0
        for index in 0..<count {
            sum += self[index]
        }
        return sum / Double(count)
    }
}
print([1260.0, 1200.0, 98.6, 37.0].average())
// Stampa "648.9".
```

Questo esempio aggiunge un metodo `average()` ai contenitori il cui tipo `Item` è `Double`. Itera sugli elementi del contenitore per sommarli, e divide per il numero di elementi del contenitore per calcolare la media. Converte esplicitamente il conteggio da `Int` a `Double` per poter eseguire una divisione in virgola mobile.

Puoi includere più requisiti in una clausola `where` generica che fa parte di un'estensione, proprio come puoi fare per una clausola `where` generica che scrivi altrove. Separa ciascun requisito dell'elenco con una virgola.

## Clausole where contestuali <a href="#clausole-where-contestuali" id="clausole-where-contestuali"></a>

Puoi scrivere una clausola `where` generica come parte di una dichiarazione che non ha propri vincoli di tipo generici, quando stai già lavorando nel contesto di tipi generici. Per esempio, puoi scrivere una clausola `where` generica sul subscript di un tipo generico o su un metodo di un'estensione di un tipo generico. La struttura `Container` è generica, e le clausole `where` dell'esempio seguente specificano quali vincoli di tipo devono essere soddisfatti per rendere disponibili questi nuovi metodi su un contenitore.

```swift
extension Container {
    func average() -> Double where Item == Int {
        var sum = 0.0
        for index in 0..<count {
            sum += Double(self[index])
        }
        return sum / Double(count)
    }
    func endsWith(_ item: Item) -> Bool where Item: Equatable {
        return count >= 1 && self[count-1] == item
    }
}
let numbers = [1260, 1200, 98, 37]
print(numbers.average())
// Stampa "648.75".
print(numbers.endsWith(37))
// Stampa "true".
```

Questo esempio aggiunge un metodo `average()` a `Container` quando gli elementi sono interi, e aggiunge un metodo `endsWith(_:)` quando gli elementi sono equatable. Entrambe le funzioni includono una clausola `where` generica che aggiunge vincoli di tipo al parametro di tipo generico `Item` della dichiarazione originale di `Container`.

Se vuoi scrivere questo codice senza usare clausole `where` contestuali, scrivi due estensioni, una per ciascuna clausola `where` generica. L'esempio qui sopra e l'esempio seguente hanno lo stesso comportamento.

```swift
extension Container where Item == Int {
    func average() -> Double {
        var sum = 0.0
        for index in 0..<count {
            sum += Double(self[index])
        }
        return sum / Double(count)
    }
}
extension Container where Item: Equatable {
    func endsWith(_ item: Item) -> Bool {
        return count >= 1 && self[count-1] == item
    }
}
```

Nella versione di questo esempio che usa clausole `where` contestuali, le implementazioni di `average()` e `endsWith(_:)` si trovano entrambe nella stessa estensione perché la clausola `where` generica di ciascun metodo dichiara i requisiti che devono essere soddisfatti per rendere disponibile quel metodo. Spostare quei requisiti nelle clausole `where` generiche delle estensioni rende i metodi disponibili nelle stesse situazioni, ma richiede un'estensione per ciascun requisito.

## Tipi associati con una clausola where generica <a href="#tipi-associati-con-una-clausola-where-generica" id="tipi-associati-con-una-clausola-where-generica"></a>

Puoi includere una clausola `where` generica su un tipo associato. Per esempio, supponi di voler creare una versione di `Container` che includa un iteratore, come quello che usa il protocollo `Sequence` nella libreria standard di Swift. Ecco come lo scrivi:

```swift
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }

    associatedtype Iterator: IteratorProtocol where Iterator.Element == Item
    func makeIterator() -> Iterator
}
```

La clausola `where` generica su `Iterator` richiede che l'iteratore attraversi elementi dello stesso tipo degli elementi del contenitore, indipendentemente dal tipo dell'iteratore. La funzione `makeIterator()` fornisce l'accesso all'iteratore di un contenitore.

Per un protocollo che eredita da un altro protocollo, aggiungi un vincolo a un tipo associato ereditato includendo la clausola `where` generica nella dichiarazione del protocollo. Per esempio, il codice seguente dichiara un protocollo `ComparableContainer` che richiede che `Item` sia conforme a `Comparable`:

```swift
protocol ComparableContainer: Container where Item: Comparable { }
```

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

I subscript possono essere generici, e possono includere clausole `where` generiche. Scrivi il nome del tipo segnaposto tra parentesi angolari dopo `subscript`, e scrivi una clausola `where` generica subito prima della parentesi graffa di apertura del corpo del subscript. Per esempio:

```swift
extension Container {
    subscript<Indices: Sequence>(indices: Indices) -> [Item]
            where Indices.Iterator.Element == Int {
        var result: [Item] = []
        for index in indices {
            result.append(self[index])
        }
        return result
    }
}
```

Questa estensione del protocollo `Container` aggiunge un subscript che accetta una sequenza di indici e restituisce un array contenente gli elementi a ciascun indice dato. Questo subscript generico è vincolato come segue:

* Il parametro generico `Indices` tra parentesi angolari deve essere un tipo conforme al protocollo `Sequence` della libreria standard di Swift.
* Il subscript accetta un unico parametro, `indices`, che è un'istanza di quel tipo `Indices`.
* La clausola `where` generica richiede che l'iteratore della sequenza attraversi elementi di tipo `Int`. Questo garantisce che gli indici della sequenza siano dello stesso tipo degli indici usati per un contenitore.

Nel loro insieme, questi vincoli significano che il valore passato per il parametro `indices` è una sequenza di interi.

## Vincoli impliciti <a href="#vincoli-impliciti" id="vincoli-impliciti"></a>

Oltre ai vincoli che scrivi esplicitamente, molti punti del tuo codice generico richiedono implicitamente anche la conformità ad alcuni protocolli molto comuni come [`Copyable`](https://developer.apple.com/documentation/swift/copyable). Questi vincoli generici che non devi scrivere sono noti come *vincoli impliciti*. Per esempio, entrambe le seguenti dichiarazioni di funzione richiedono che `MyType` sia copiabile:

```swift
function someFunction<MyType> { ... }
function someFunction<MyType: Copyable> { ... }
```

Nel codice qui sopra, la prima dichiarazione ha un vincolo implicito, e la seconda versione elenca esplicitamente la conformità. Nella maggior parte del codice, anche i tipi sono implicitamente conformi a questi protocolli comuni. Per maggiori informazioni, vedi [Conformità implicita a un protocollo](/guida-al-linguaggio/protocolli.md#conformita-implicita-a-un-protocollo).

Poiché la maggior parte dei tipi in Swift è conforme a questi protocolli, scriverli quasi ovunque sarebbe ripetitivo. Invece, contrassegnando solo le eccezioni, evidenzi i punti che omettono un vincolo comune. Per sopprimere un vincolo implicito, scrivi il nome del protocollo preceduto da una tilde (`~`). Puoi leggere `~Copyable` come "forse copiabile" — questo vincolo soppresso consente in questa posizione sia tipi copiabili sia tipi non copiabili. Nota che `~Copyable` non *richiede* che il tipo sia non copiabile. Per esempio:

```swift
func f<MyType>(x: inout MyType) {
    let x1 = x  // Il valore di x1 è una copia del valore di x.
    let x2 = x  // Il valore di x2 è una copia del valore di x.
}

func g<AnotherType: ~Copyable>(y: inout AnotherType) {
    let y1 = y  // L'assegnamento consuma il valore di y.
    let y2 = y  // Errore: valore consumato più di una volta.
}
```

Nel codice qui sopra, la funzione `f()` richiede implicitamente che `MyType` sia copiabile. All'interno del corpo della funzione, il valore di `x` viene copiato in `x1` e in `x2` nell'assegnamento. Al contrario, `g()` sopprime il vincolo implicito su `AnotherType`, il che ti permette di passare un valore copiabile oppure non copiabile. All'interno del corpo della funzione, non puoi copiare il valore di `y` perché `AnotherType` potrebbe essere non copiabile. L'assegnamento consuma il valore di `y` ed è un errore consumare quel valore più di una volta. I valori non copiabili come `y` devono essere passati come parametri in-out, borrowing o consuming — per maggiori informazioni, vedi [Parametri borrowing e consuming](/riferimento-del-linguaggio/dichiarazioni.md#parametri-borrowing-e-consuming).

Per i dettagli su quando il codice generico include un vincolo implicito verso un dato protocollo, vedi la documentazione di riferimento di quel protocollo.
