> 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/controllo-degli-accessi.md).

# Controllo degli accessi (Access Control)

Gestisci la visibilità del codice per dichiarazione, file e modulo.

Il *controllo degli accessi* limita l'accesso a parti del tuo codice da parte del codice di altri file sorgente e moduli. Questa funzionalità ti permette di nascondere i dettagli di implementazione del tuo codice, e di specificare un'interfaccia preferenziale attraverso cui quel codice può essere acceduto e usato.

Puoi assegnare livelli di accesso specifici ai singoli tipi (classi, strutture ed enumerazioni), così come a proprietà, metodi, inizializzatori e subscript che appartengono a quei tipi. I protocolli possono essere limitati a un certo contesto, così come le costanti, le variabili e le funzioni globali.

Oltre a offrire vari livelli di controllo degli accessi, Swift riduce la necessità di specificare livelli espliciti di controllo degli accessi fornendo livelli di accesso predefiniti per gli scenari tipici. Anzi, se stai scrivendo un'app a target singolo, potresti non aver bisogno di specificare alcun livello esplicito di controllo degli accessi.

{% hint style="info" %}
**Nota:** I vari aspetti del tuo codice a cui può essere applicato il controllo degli accessi (proprietà, tipi, funzioni e così via) sono chiamati, per brevità, “entità” nelle sezioni seguenti.
{% endhint %}

## Moduli, file sorgente e package <a href="#moduli-file-sorgente-e-package" id="moduli-file-sorgente-e-package"></a>

Il modello di controllo degli accessi di Swift si basa sul concetto di moduli, file sorgente e package.

Un *modulo* è una singola unità di distribuzione del codice — un framework o un'applicazione compilati e distribuiti come un'unica unità e che possono essere importati da un altro modulo con la parola chiave `import` di Swift.

Ogni target di compilazione (come un bundle di app o un framework) in Xcode è trattato come un modulo separato in Swift. Se raggruppi parti del codice della tua app in un framework autonomo — magari per incapsulare e riutilizzare quel codice in più applicazioni — allora tutto ciò che definisci all'interno di quel framework farà parte di un modulo separato quando viene importato e usato all'interno di un'app, o quando viene usato all'interno di un altro framework.

Un *file sorgente* è un singolo file di codice sorgente Swift all'interno di un modulo (di fatto, un singolo file all'interno di un'app o di un framework). Sebbene sia comune definire i singoli tipi in file sorgente separati, un singolo file sorgente può contenere definizioni di più tipi, funzioni e così via.

Un *package* è un gruppo di moduli che sviluppi come un'unità. Definisci i moduli che formano un package come parte della configurazione del sistema di build che stai usando, non come parte del tuo codice sorgente Swift. Per esempio, se usi Swift Package Manager per compilare il tuo codice, definisci un package nel tuo file `Package.swift` usando le API del modulo [PackageDescription](https://developer.apple.com/documentation/packagedescription), e se usi Xcode, specifichi il nome del package nell'impostazione di build Package Access Identifier.

## Livelli di accesso <a href="#livelli-di-accesso" id="livelli-di-accesso"></a>

Swift fornisce sei diversi *livelli di accesso* per le entità all'interno del tuo codice. Questi livelli di accesso sono relativi al file sorgente in cui un'entità è definita, al modulo a cui quel file sorgente appartiene, e al package a cui il modulo appartiene.

* L'*accesso open* e l'*accesso public* permettono di usare le entità in qualsiasi file sorgente del modulo che le definisce, e anche in un file sorgente di un altro modulo che importa il modulo che le definisce. Di solito usi l'accesso open o public quando specifichi l'interfaccia pubblica di un framework. La differenza tra accesso open e public è descritta più avanti.
* L'*accesso package* permette di usare le entità in qualsiasi file sorgente del package che le definisce ma non in alcun file sorgente al di fuori di quel package. Di solito usi l'accesso package all'interno di un'app o di un framework strutturato in più moduli.
* L'*accesso internal* permette di usare le entità in qualsiasi file sorgente del modulo che le definisce, ma non in alcun file sorgente al di fuori di quel modulo. Di solito usi l'accesso internal quando definisci la struttura interna di un'app o di un framework.
* L'*accesso file-private* limita l'uso di un'entità al file sorgente in cui è definita. Usa l'accesso file-private per nascondere i dettagli di implementazione di una specifica porzione di funzionalità quando tali dettagli vengono usati all'interno di un intero file.
* L'*accesso private* limita l'uso di un'entità alla dichiarazione che la racchiude, e alle estensioni di quella dichiarazione che si trovano nello stesso file. Usa l'accesso private per nascondere i dettagli di implementazione di una specifica porzione di funzionalità quando tali dettagli vengono usati solo all'interno di una singola dichiarazione.

L'accesso open è il livello di accesso più alto (meno restrittivo) e l'accesso private è il livello di accesso più basso (più restrittivo).

L'accesso open si applica solo alle classi e ai membri delle classi, e differisce dall'accesso public perché consente al codice esterno al modulo di creare sottoclassi ed eseguire override, come discusso più avanti in [Creazione di sottoclassi](/guida-al-linguaggio/controllo-degli-accessi.md#creazione-di-sottoclassi). Contrassegnare una classe come open indica esplicitamente che hai considerato l'impatto del codice di altri moduli che usa quella classe come superclasse, e che hai progettato il codice della tua classe di conseguenza.

### Principio guida dei livelli di accesso <a href="#principio-guida-dei-livelli-di-accesso" id="principio-guida-dei-livelli-di-accesso"></a>

I livelli di accesso in Swift seguono un principio guida generale: *nessuna entità può essere definita in termini di un'altra entità che ha un livello di accesso inferiore (più restrittivo).*

Per esempio:

* Una variabile public non può essere definita come avente un tipo internal, file-private o private, perché il tipo potrebbe non essere disponibile ovunque venga usata la variabile public.
* Una funzione non può avere un livello di accesso più alto dei tipi dei suoi parametri e del suo tipo di ritorno, perché la funzione potrebbe essere usata in situazioni in cui i tipi che la costituiscono non sono disponibili al codice circostante.

Le implicazioni specifiche di questo principio guida per i diversi aspetti del linguaggio sono trattate in dettaglio più avanti.

### Livelli di accesso predefiniti <a href="#livelli-di-accesso-predefiniti" id="livelli-di-accesso-predefiniti"></a>

Tutte le entità del tuo codice (con alcune eccezioni specifiche, come descritto più avanti in questo capitolo) hanno un livello di accesso predefinito internal se non specifichi tu stesso un livello di accesso esplicito. Di conseguenza, in molti casi non hai bisogno di specificare un livello di accesso esplicito nel tuo codice.

### Livelli di accesso per app a target singolo <a href="#livelli-di-accesso-per-app-a-target-singolo" id="livelli-di-accesso-per-app-a-target-singolo"></a>

Quando scrivi una semplice app a target singolo, il codice della tua app è tipicamente autocontenuto all'interno dell'app e non ha bisogno di essere reso disponibile al di fuori del modulo dell'app. Il livello di accesso predefinito internal soddisfa già questo requisito. Pertanto, non hai bisogno di specificare un livello di accesso personalizzato. Potresti, tuttavia, voler contrassegnare alcune parti del tuo codice come file private o private per nasconderne i dettagli di implementazione ad altro codice all'interno del modulo dell'app.

### Livelli di accesso per i framework <a href="#livelli-di-accesso-per-i-framework" id="livelli-di-accesso-per-i-framework"></a>

Quando sviluppi un framework, contrassegna l'interfaccia pubblica di quel framework come open o public affinché possa essere vista e acceduta da altri moduli, come un'app che importa il framework. Questa interfaccia pubblica è l'interfaccia di programmazione dell'applicazione (o API) del framework.

{% hint style="info" %}
**Nota:** Qualsiasi dettaglio di implementazione interno del tuo framework può comunque usare il livello di accesso predefinito internal, oppure può essere contrassegnato come private o file private se vuoi nasconderlo ad altre parti del codice interno del framework. Devi contrassegnare un'entità come open o public solo se vuoi che diventi parte dell'API del tuo framework.
{% endhint %}

### Livelli di accesso per i target di unit test <a href="#livelli-di-accesso-per-i-target-di-unit-test" id="livelli-di-accesso-per-i-target-di-unit-test"></a>

Quando scrivi un'app con un target di unit test, il codice della tua app deve essere reso disponibile a quel modulo per poter essere testato. Per impostazione predefinita, solo le entità contrassegnate come open o public sono accessibili ad altri moduli. Tuttavia, un target di unit test può accedere a qualsiasi entità internal, se contrassegni la dichiarazione di import di un modulo prodotto con l'attributo `@testable` e compili quel modulo prodotto con i test abilitati.

## Sintassi del controllo degli accessi <a href="#sintassi-del-controllo-degli-accessi" id="sintassi-del-controllo-degli-accessi"></a>

Definisci il livello di accesso di un'entità collocando uno dei modificatori elencati in [Livelli di accesso](/guida-al-linguaggio/controllo-degli-accessi.md#livelli-di-accesso), come `public` o `private`, all'inizio della dichiarazione dell'entità. Per esempio:

```swift
public class SomePublicClass {}
internal struct SomeInternalStruct() {}
private func somePrivateFunction() {}
```

Il codice qui sopra dichiara `SomePublicClass` come public, `SomeInternalStruct` come internal, e `somePrivateFunction()` come private. Se non scrivi un livello di accesso esplicito, il modificatore del livello di accesso predefinito è `internal`, come descritto in [Livelli di accesso predefiniti](/guida-al-linguaggio/controllo-degli-accessi.md#livelli-di-accesso-predefiniti). Per esempio, nel codice seguente, `SomeInternalStruct` è implicitamente internal:

```swift
struct SomeInternalStruct() {}
```

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

Se vuoi specificare un livello di accesso esplicito per un tipo personalizzato, fallo nel punto in cui definisci il tipo. Il nuovo tipo può quindi essere usato ovunque il suo livello di accesso lo consenta. Per esempio, se definisci una classe file-private, quella classe può essere usata come tipo di una proprietà, o come tipo di un parametro o di ritorno di una funzione, solo nel file sorgente in cui la classe file-private è definita.

Il livello di controllo degli accessi di un tipo influisce anche sul livello di accesso predefinito dei *membri* di quel tipo (le sue proprietà, i suoi metodi, inizializzatori e subscript). Se definisci il livello di accesso di un tipo come private o file private, anche il livello di accesso predefinito dei suoi membri sarà private o file private. Se definisci il livello di accesso di un tipo come internal o public (o usi il livello di accesso predefinito internal senza specificare esplicitamente un livello di accesso), il livello di accesso predefinito dei membri del tipo sarà internal.

{% hint style="warning" %}
**Importante:** Un tipo public ha per impostazione predefinita membri internal, non membri public. Se vuoi che un membro del tipo sia public, devi contrassegnarlo esplicitamente come tale. Questo requisito garantisce che l'API pubblica di un tipo sia qualcosa che scegli deliberatamente di pubblicare, ed evita di presentare per errore il funzionamento interno di un tipo come API pubblica.
{% endhint %}

```swift
public class SomePublicClass {                   // classe esplicitamente public
    public var somePublicProperty = 0            // membro di classe esplicitamente public
    var someInternalProperty = 0                 // membro di classe implicitamente internal
    fileprivate func someFilePrivateMethod() {}  // membro di classe esplicitamente file-private
    private func somePrivateMethod() {}          // membro di classe esplicitamente private
}

class SomeInternalClass {                        // classe implicitamente internal
    var someInternalProperty = 0                 // membro di classe implicitamente internal
    fileprivate func someFilePrivateMethod() {}  // membro di classe esplicitamente file-private
    private func somePrivateMethod() {}          // membro di classe esplicitamente private
}

fileprivate class SomeFilePrivateClass {         // classe esplicitamente file-private
    func someFilePrivateMethod() {}              // membro di classe implicitamente file-private
    private func somePrivateMethod() {}          // membro di classe esplicitamente private
}

private class SomePrivateClass {                 // classe esplicitamente private
    func somePrivateMethod() {}                  // membro di classe implicitamente private
}
```

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

Il livello di accesso di un tipo tupla è il livello di accesso più restrittivo tra tutti i tipi usati in quella tupla. Per esempio, se componi una tupla a partire da due tipi diversi, uno con accesso internal e uno con accesso private, il livello di accesso di quel tipo tupla composto sarà private.

{% hint style="info" %}
**Nota:** I tipi tupla non hanno una definizione autonoma nel modo in cui ce l'hanno classi, strutture, enumerazioni e funzioni. Il livello di accesso di un tipo tupla viene determinato automaticamente dai tipi che compongono il tipo tupla, e non può essere specificato esplicitamente.
{% endhint %}

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

Il livello di accesso di un tipo funzione viene calcolato come il livello di accesso più restrittivo tra i tipi dei parametri e il tipo di ritorno della funzione. Devi specificare esplicitamente il livello di accesso come parte della definizione della funzione se il livello di accesso calcolato della funzione non corrisponde a quello predefinito del contesto.

L'esempio seguente definisce una funzione globale chiamata `someFunction()`, senza fornire uno specifico modificatore del livello di accesso per la funzione stessa. Potresti aspettarti che questa funzione abbia il livello di accesso predefinito “internal”, ma non è così. In effetti, `someFunction()` non compila così come è scritta qui sotto:

```swift
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // qui va l'implementazione della funzione
}
```

Il tipo di ritorno della funzione è un tipo tupla composto da due delle classi personalizzate definite sopra in [Tipi personalizzati](/guida-al-linguaggio/controllo-degli-accessi.md#tipi-personalizzati). Una di queste classi è definita come internal, e l'altra è definita come private. Pertanto, il livello di accesso complessivo del tipo tupla composto è private (il livello di accesso minimo tra i tipi che costituiscono la tupla).

Poiché il tipo di ritorno della funzione è private, devi contrassegnare il livello di accesso complessivo della funzione con il modificatore `private` affinché la dichiarazione della funzione sia valida:

```swift
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // qui va l'implementazione della funzione
}
```

Non è valido contrassegnare la definizione di `someFunction()` con i modificatori `public` o `internal`, né usare l'impostazione predefinita internal, perché gli utenti public o internal della funzione potrebbero non avere un accesso appropriato alla classe private usata nel tipo di ritorno della funzione.

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

I singoli casi di un'enumerazione ricevono automaticamente lo stesso livello di accesso dell'enumerazione a cui appartengono. Non puoi specificare un livello di accesso diverso per i singoli casi dell'enumerazione.

Nell'esempio seguente, l'enumerazione `CompassPoint` ha un livello di accesso esplicito public. Anche i casi dell'enumerazione `north`, `south`, `east` e `west` hanno quindi un livello di accesso public:

```swift
public enum CompassPoint {
    case north
    case south
    case east
    case west
}
```

#### Valori grezzi e valori associati <a href="#valori-grezzi-e-valori-associati" id="valori-grezzi-e-valori-associati"></a>

I tipi usati per i valori grezzi o per i valori associati nella definizione di un'enumerazione devono avere un livello di accesso almeno pari a quello dell'enumerazione. Per esempio, non puoi usare un tipo private come tipo del valore grezzo di un'enumerazione con un livello di accesso internal.

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

Il livello di accesso di un tipo annidato è lo stesso del tipo che lo contiene, a meno che il tipo che lo contiene non sia public. I tipi annidati definiti all'interno di un tipo public hanno automaticamente un livello di accesso internal. Se vuoi che un tipo annidato all'interno di un tipo public sia disponibile pubblicamente, devi dichiarare esplicitamente il tipo annidato come public.

## Creazione di sottoclassi <a href="#creazione-di-sottoclassi" id="creazione-di-sottoclassi"></a>

Puoi creare una sottoclasse di qualsiasi classe che sia accessibile nel contesto di accesso corrente e che sia definita nello stesso modulo della sottoclasse. Puoi anche creare una sottoclasse di qualsiasi classe open definita in un modulo diverso. Una sottoclasse non può avere un livello di accesso più alto della sua superclasse — per esempio, non puoi scrivere una sottoclasse public di una superclasse internal.

Inoltre, per le classi definite nello stesso modulo, puoi sovrascrivere qualsiasi membro della classe (metodo, proprietà, inizializzatore o subscript) visibile in un certo contesto di accesso. Per le classi definite in un altro modulo, puoi sovrascrivere qualsiasi membro di classe open.

Un override può rendere un membro di classe ereditato più accessibile rispetto alla sua versione nella superclasse. Nell'esempio seguente, la classe `A` è una classe public con un metodo file-private chiamato `someMethod()`. La classe `B` è una sottoclasse di `A`, con un livello di accesso ridotto a “internal”. Ciononostante, la classe `B` fornisce un override di `someMethod()` con un livello di accesso “internal”, che è *più alto* rispetto all'implementazione originale di `someMethod()`:

```swift
public class A {
    fileprivate func someMethod() {}
}

internal class B: A {
    override internal func someMethod() {}
}
```

È persino valido che un membro di una sottoclasse chiami un membro della superclasse che ha permessi di accesso più bassi del membro della sottoclasse, purché la chiamata al membro della superclasse avvenga all'interno di un contesto di livello di accesso consentito (cioè, all'interno dello stesso file sorgente della superclasse per una chiamata a un membro file-private, o all'interno dello stesso modulo della superclasse per una chiamata a un membro internal):

```swift
public class A {
    fileprivate func someMethod() {}
}

internal class B: A {
    override internal func someMethod() {
        super.someMethod()
    }
}
```

Poiché la superclasse `A` e la sottoclasse `B` sono definite nello stesso file sorgente, è valido che l'implementazione di `someMethod()` di `B` chiami `super.someMethod()`.

## Costanti, variabili, proprietà e subscript <a href="#costanti-variabili-proprieta-e-subscript" id="costanti-variabili-proprieta-e-subscript"></a>

Una costante, una variabile o una proprietà non può essere più pubblica del suo tipo. Non è valido, per esempio, scrivere una proprietà public con un tipo private. Analogamente, un subscript non può essere più pubblico né del suo tipo di indice né del suo tipo di ritorno.

Se una costante, una variabile, una proprietà o un subscript fa uso di un tipo private, anche la costante, la variabile, la proprietà o il subscript deve essere contrassegnato come `private`:

```swift
private var privateInstance = SomePrivateClass()
```

### Getter e setter <a href="#getter-e-setter" id="getter-e-setter"></a>

I getter e i setter di costanti, variabili, proprietà e subscript ricevono automaticamente lo stesso livello di accesso della costante, variabile, proprietà o subscript a cui appartengono.

Puoi dare a un setter un livello di accesso *più basso* del getter corrispondente, per limitare l'ambito di lettura e scrittura di quella variabile, proprietà o subscript. Assegni un livello di accesso più basso scrivendo `fileprivate(set)`, `private(set)`, `internal(set)` o `package(set)` prima dell'introduttore `var` o `subscript`.

{% hint style="info" %}
**Nota:** Questa regola si applica sia alle proprietà memorizzate sia alle proprietà calcolate. Anche se non scrivi un getter e un setter espliciti per una proprietà memorizzata, Swift sintetizza comunque per te un getter e un setter impliciti per fornire l'accesso alla memoria sottostante della proprietà memorizzata. Usa `fileprivate(set)`, `private(set)`, `internal(set)` e `package(set)` per cambiare il livello di accesso di questo setter sintetizzato esattamente nello stesso modo di un setter esplicito in una proprietà calcolata.
{% endhint %}

L'esempio seguente definisce una struttura chiamata `TrackedString`, che tiene traccia del numero di volte in cui una proprietà stringa viene modificata:

```swift
struct TrackedString {
    private(set) var numberOfEdits = 0
    var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
}
```

La struttura `TrackedString` definisce una proprietà stringa memorizzata chiamata `value`, con un valore iniziale di `""` (una stringa vuota). La struttura definisce anche una proprietà intera memorizzata chiamata `numberOfEdits`, che viene usata per tenere traccia del numero di volte in cui `value` viene modificata. Questo tracciamento delle modifiche è implementato con un osservatore di proprietà `didSet` sulla proprietà `value`, che incrementa `numberOfEdits` ogni volta che la proprietà `value` viene impostata a un nuovo valore.

La struttura `TrackedString` e la proprietà `value` non forniscono un modificatore esplicito del livello di accesso, e quindi ricevono entrambe il livello di accesso predefinito internal. Tuttavia, il livello di accesso della proprietà `numberOfEdits` è contrassegnato con un modificatore `private(set)` per indicare che il getter della proprietà ha ancora il livello di accesso predefinito internal, ma la proprietà è impostabile solo dall'interno del codice che fa parte della struttura `TrackedString`. Questo permette a `TrackedString` di modificare internamente la proprietà `numberOfEdits`, ma di presentare la proprietà come proprietà di sola lettura quando viene usata al di fuori della definizione della struttura.

Se crei un'istanza di `TrackedString` e modifichi alcune volte il suo valore stringa, puoi vedere il valore della proprietà `numberOfEdits` aggiornarsi in base al numero di modifiche:

```swift
var stringToEdit = TrackedString()
stringToEdit.value = "This string will be tracked."
stringToEdit.value += " This edit will increment numberOfEdits."
stringToEdit.value += " So will this one."
print("The number of edits is \(stringToEdit.numberOfEdits)")
// Stampa "The number of edits is 3".
```

Sebbene tu possa interrogare il valore corrente della proprietà `numberOfEdits` dall'interno di un altro file sorgente, non puoi *modificare* la proprietà da un altro file sorgente. Questa restrizione protegge i dettagli di implementazione della funzionalità di tracciamento delle modifiche di `TrackedString`, pur fornendo un comodo accesso a un aspetto di quella funzionalità.

Nota che, se necessario, puoi assegnare un livello di accesso esplicito sia a un getter sia a un setter. L'esempio seguente mostra una versione della struttura `TrackedString` in cui la struttura è definita con un livello di accesso esplicito public. I membri della struttura (compresa la proprietà `numberOfEdits`) hanno quindi per impostazione predefinita un livello di accesso internal. Puoi rendere public il getter della proprietà `numberOfEdits` della struttura, e private il suo setter, combinando i modificatori del livello di accesso `public` e `private(set)`:

```swift
public struct TrackedString {
    public private(set) var numberOfEdits = 0
    public var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
    public init() {}
}
```

## Inizializzatori <a href="#inizializzatori" id="inizializzatori"></a>

Agli inizializzatori personalizzati può essere assegnato un livello di accesso minore o uguale a quello del tipo che inizializzano. L'unica eccezione riguarda gli inizializzatori required (come definiti in [Inizializzatori required](/guida-al-linguaggio/inizializzazione.md#inizializzatori-required)). Un inizializzatore required deve avere lo stesso livello di accesso della classe a cui appartiene.

Come per i parametri di funzioni e metodi, i tipi dei parametri di un inizializzatore non possono essere più privati del livello di accesso dell'inizializzatore stesso.

### Inizializzatori predefiniti <a href="#inizializzatori-predefiniti" id="inizializzatori-predefiniti"></a>

Come descritto in [Inizializzatori predefiniti](/guida-al-linguaggio/inizializzazione.md#inizializzatori-predefiniti), Swift fornisce automaticamente un *inizializzatore predefinito* senza argomenti per qualsiasi struttura o classe base che fornisca valori predefiniti per tutte le sue proprietà e non fornisca essa stessa almeno un inizializzatore.

Un inizializzatore predefinito ha lo stesso livello di accesso del tipo che inizializza, a meno che quel tipo non sia definito come `public`. Per un tipo definito come `public`, l'inizializzatore predefinito è considerato internal. Se vuoi che un tipo public sia inizializzabile con un inizializzatore senza argomenti quando viene usato in un altro modulo, devi fornire esplicitamente tu stesso un inizializzatore public senza argomenti come parte della definizione del tipo.

### Inizializzatori memberwise predefiniti per i tipi struttura <a href="#inizializzatori-memberwise-predefiniti-per-i-tipi-struttura" id="inizializzatori-memberwise-predefiniti-per-i-tipi-struttura"></a>

L'inizializzatore memberwise predefinito di un tipo struttura è considerato private se una qualsiasi delle proprietà memorizzate della struttura è private. Allo stesso modo, se una qualsiasi delle proprietà memorizzate della struttura è file private, l'inizializzatore è file private. Altrimenti, l'inizializzatore ha un livello di accesso internal.

Come per l'inizializzatore predefinito visto sopra, se vuoi che un tipo struttura public sia inizializzabile con un inizializzatore memberwise quando viene usato in un altro modulo, devi fornire tu stesso un inizializzatore memberwise public come parte della definizione del tipo.

## Protocolli <a href="#protocolli" id="protocolli"></a>

Se vuoi assegnare un livello di accesso esplicito a un tipo protocollo, fallo nel punto in cui definisci il protocollo. Questo ti permette di creare protocolli che possono essere adottati solo all'interno di un certo contesto di accesso.

Il livello di accesso di ciascun requisito all'interno della definizione di un protocollo viene impostato automaticamente allo stesso livello di accesso del protocollo. Non puoi impostare un requisito del protocollo a un livello di accesso diverso da quello del protocollo che supporta. Questo garantisce che tutti i requisiti del protocollo siano visibili su qualsiasi tipo che adotta il protocollo.

{% hint style="info" %}
**Nota:** Se definisci un protocollo public, i requisiti del protocollo richiedono un livello di accesso public per quei requisiti quando vengono implementati. Questo comportamento è diverso da quello degli altri tipi, in cui la definizione di un tipo public implica un livello di accesso internal per i membri del tipo.
{% endhint %}

### Ereditarietà dei protocolli <a href="#ereditarieta-dei-protocolli" id="ereditarieta-dei-protocolli"></a>

Se definisci un nuovo protocollo che eredita da un protocollo esistente, il nuovo protocollo può avere al massimo lo stesso livello di accesso del protocollo da cui eredita. Per esempio, non puoi scrivere un protocollo public che eredita da un protocollo internal.

### Conformità ai protocolli <a href="#conformita-ai-protocolli" id="conformita-ai-protocolli"></a>

Un tipo può essere conforme a un protocollo con un livello di accesso più basso del tipo stesso. Per esempio, puoi definire un tipo public che può essere usato in altri moduli, ma la cui conformità a un protocollo internal può essere usata solo all'interno del modulo che definisce il protocollo internal.

Il contesto in cui un tipo è conforme a un particolare protocollo è il minimo tra il livello di accesso del tipo e il livello di accesso del protocollo. Per esempio, se un tipo è public, ma un protocollo a cui è conforme è internal, anche la conformità del tipo a quel protocollo è internal.

Quando scrivi o estendi un tipo affinché sia conforme a un protocollo, devi assicurarti che l'implementazione di ciascun requisito del protocollo da parte del tipo abbia almeno lo stesso livello di accesso della conformità del tipo a quel protocollo. Per esempio, se un tipo public è conforme a un protocollo internal, l'implementazione di ciascun requisito del protocollo da parte del tipo deve essere almeno internal.

{% hint style="info" %}
**Nota:** In Swift, come in Objective-C, la conformità ai protocolli è globale — non è possibile che un tipo sia conforme a un protocollo in due modi diversi all'interno dello stesso programma.
{% endhint %}

## Estensioni <a href="#estensioni" id="estensioni"></a>

Puoi estendere una classe, una struttura o un'enumerazione in qualsiasi contesto di accesso in cui la classe, la struttura o l'enumerazione è disponibile. Qualsiasi membro di tipo aggiunto in un'estensione ha lo stesso livello di accesso predefinito dei membri di tipo dichiarati nel tipo originale che viene esteso. Se estendi un tipo public o internal, qualsiasi nuovo membro di tipo che aggiungi ha un livello di accesso predefinito internal. Se estendi un tipo file-private, qualsiasi nuovo membro di tipo che aggiungi ha un livello di accesso predefinito file private. Se estendi un tipo private, qualsiasi nuovo membro di tipo che aggiungi ha un livello di accesso predefinito private.

In alternativa, puoi contrassegnare un'estensione con un modificatore esplicito del livello di accesso (per esempio, `private`) per impostare un nuovo livello di accesso predefinito per tutti i membri definiti all'interno dell'estensione. Questo nuovo valore predefinito può comunque essere sovrascritto all'interno dell'estensione per i singoli membri di tipo.

Non puoi fornire un modificatore esplicito del livello di accesso per un'estensione se stai usando quell'estensione per aggiungere la conformità a un protocollo. Viene invece usato il livello di accesso del protocollo stesso per fornire il livello di accesso predefinito per l'implementazione di ciascun requisito del protocollo all'interno dell'estensione.

### Membri private nelle estensioni <a href="#membri-private-nelle-estensioni" id="membri-private-nelle-estensioni"></a>

Le estensioni che si trovano nello stesso file della classe, della struttura o dell'enumerazione che estendono si comportano come se il codice dell'estensione fosse stato scritto come parte della dichiarazione del tipo originale. Di conseguenza, puoi:

* Dichiarare un membro private nella dichiarazione originale, e accedere a quel membro dalle estensioni nello stesso file.
* Dichiarare un membro private in un'estensione, e accedere a quel membro da un'altra estensione nello stesso file.
* Dichiarare un membro private in un'estensione, e accedere a quel membro dalla dichiarazione originale nello stesso file.

Questo comportamento significa che puoi usare le estensioni nello stesso modo per organizzare il tuo codice, indipendentemente dal fatto che i tuoi tipi abbiano entità private. Per esempio, dato il seguente semplice protocollo:

```swift
protocol SomeProtocol {
    func doSomething()
}
```

Puoi usare un'estensione per aggiungere la conformità al protocollo, in questo modo:

```swift
struct SomeStruct {
    private var privateVariable = 12
}

extension SomeStruct: SomeProtocol {
    func doSomething() {
        print(privateVariable)
    }
}
```

## Generici <a href="#generici" id="generici"></a>

Il livello di accesso di un tipo generico o di una funzione generica è il minimo tra il livello di accesso del tipo o della funzione generica stessa e il livello di accesso di eventuali vincoli di tipo sui suoi parametri di tipo.

## Alias di tipo <a href="#alias-di-tipo" id="alias-di-tipo"></a>

Qualsiasi alias di tipo che definisci è trattato come un tipo distinto ai fini del controllo degli accessi. Un alias di tipo può avere un livello di accesso minore o uguale al livello di accesso del tipo di cui è alias. Per esempio, un alias di tipo private può essere alias di un tipo private, file-private, internal, public o open, ma un alias di tipo public non può essere alias di un tipo internal, file-private o private.

{% hint style="info" %}
**Nota:** Questa regola si applica anche agli alias di tipo per i tipi associati usati per soddisfare le conformità ai protocolli.
{% endhint %}
