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

# Ereditarietà (Inheritance)

Crea sottoclassi per aggiungere o sovrascrivere funzionalità.

Una classe può *ereditare* metodi, proprietà e altre caratteristiche da un'altra classe. Quando una classe eredita da un'altra, la classe che eredita è detta *sottoclasse*, e la classe da cui eredita è detta la sua *superclasse*. L'ereditarietà è un comportamento fondamentale che distingue le classi dagli altri tipi in Swift.

In Swift le classi possono chiamare e accedere a metodi, proprietà e subscript appartenenti alla loro superclasse e possono fornire proprie versioni sovrascritte di quei metodi, proprietà e subscript per affinarne o modificarne il comportamento. Swift aiuta a garantire che i tuoi override siano corretti verificando che la definizione di override abbia una definizione corrispondente nella superclasse.

Le classi possono anche aggiungere osservatori di proprietà alle proprietà ereditate per ricevere una notifica quando il valore di una proprietà cambia. Gli osservatori di proprietà possono essere aggiunti a qualsiasi proprietà, indipendentemente dal fatto che sia stata originariamente definita come proprietà memorizzata o calcolata.

## Definire una classe base <a href="#definire-una-classe-base" id="definire-una-classe-base"></a>

Qualsiasi classe che non eredita da un'altra classe è detta *classe base*.

{% hint style="info" %}
**Nota:** Le classi Swift non ereditano da una classe base universale. Le classi che definisci senza specificare una superclasse diventano automaticamente classi base su cui puoi costruire.
{% endhint %}

L'esempio seguente definisce una classe base chiamata `Vehicle`. Questa classe base definisce una proprietà memorizzata chiamata `currentSpeed`, con un valore predefinito di `0.0` (da cui viene inferito un tipo di proprietà `Double`). Il valore della proprietà `currentSpeed` viene usato da una proprietà calcolata di sola lettura di tipo `String` chiamata `description` per creare una descrizione del veicolo.

La classe base `Vehicle` definisce anche un metodo chiamato `makeNoise`. Questo metodo in realtà non fa nulla per un'istanza di base di `Vehicle`, ma verrà personalizzato più avanti dalle sottoclassi di `Vehicle`:

```swift
class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        // non fa nulla - un veicolo qualsiasi non fa necessariamente rumore
    }
}
```

Crei una nuova istanza di `Vehicle` con la *sintassi di inizializzazione*, che si scrive come un nome di tipo seguito da parentesi vuote:

```swift
let someVehicle = Vehicle()
```

Dopo aver creato una nuova istanza di `Vehicle`, puoi accedere alla sua proprietà `description` per stampare una descrizione leggibile della velocità attuale del veicolo:

```swift
print("Vehicle: \(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour
```

La classe `Vehicle` definisce le caratteristiche comuni di un veicolo qualsiasi, ma di per sé non è molto utile. Per renderla più utile, devi affinarla per descrivere tipi di veicoli più specifici.

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

La *creazione di sottoclassi* (subclassing) è l'atto di basare una nuova classe su una classe esistente. La sottoclasse eredita le caratteristiche dalla classe esistente, che puoi poi affinare. Puoi anche aggiungere nuove caratteristiche alla sottoclasse.

Per indicare che una sottoclasse ha una superclasse, scrivi il nome della sottoclasse prima del nome della superclasse, separati da due punti:

```swift
class SomeSubclass: SomeSuperclass {
    // qui va la definizione della sottoclasse
}
```

L'esempio seguente definisce una sottoclasse chiamata `Bicycle`, con superclasse `Vehicle`:

```swift
class Bicycle: Vehicle {
    var hasBasket = false
}
```

La nuova classe `Bicycle` acquisisce automaticamente tutte le caratteristiche di `Vehicle`, come le sue proprietà `currentSpeed` e `description` e il suo metodo `makeNoise()`.

Oltre alle caratteristiche che eredita, la classe `Bicycle` definisce una nuova proprietà memorizzata, `hasBasket`, con un valore predefinito di `false` (da cui viene inferito un tipo `Bool` per la proprietà).

Per impostazione predefinita, qualsiasi nuova istanza di `Bicycle` che crei non avrà un cestino. Puoi impostare la proprietà `hasBasket` a `true` per una particolare istanza di `Bicycle` dopo che quell'istanza è stata creata:

```swift
let bicycle = Bicycle()
bicycle.hasBasket = true
```

Puoi anche modificare la proprietà ereditata `currentSpeed` di un'istanza di `Bicycle`, e interrogare la proprietà ereditata `description` dell'istanza:

```swift
bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour
```

Le sottoclassi possono a loro volta avere sottoclassi. L'esempio successivo crea una sottoclasse di `Bicycle` per una bicicletta a due posti nota come “tandem”:

```swift
class Tandem: Bicycle {
    var currentNumberOfPassengers = 0
}
```

`Tandem` eredita tutte le proprietà e i metodi di `Bicycle`, che a sua volta eredita tutte le proprietà e i metodi di `Vehicle`. La sottoclasse `Tandem` aggiunge inoltre una nuova proprietà memorizzata chiamata `currentNumberOfPassengers`, con un valore predefinito di `0`.

Se crei un'istanza di `Tandem`, puoi lavorare con qualsiasi sua proprietà, nuova o ereditata, e interrogare la proprietà di sola lettura `description` che eredita da `Vehicle`:

```swift
let tandem = Tandem()
tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0
print("Tandem: \(tandem.description)")
// Tandem: traveling at 22.0 miles per hour
```

## Override <a href="#override" id="override"></a>

Una sottoclasse può fornire una propria implementazione personalizzata di un metodo di istanza, un metodo di tipo, una proprietà di istanza, una proprietà di tipo o un subscript che altrimenti erediterebbe da una superclasse. Questo è noto come *override* (sovrascrittura).

Per sovrascrivere una caratteristica che altrimenti verrebbe ereditata, anteponi alla tua definizione di override la parola chiave `override`. Così facendo chiarisci che intendi fornire un override e che non hai fornito per errore una definizione corrispondente. Un override accidentale può causare un comportamento inatteso, e qualsiasi override privo della parola chiave `override` viene diagnosticato come errore quando il tuo codice viene compilato.

La parola chiave `override` spinge inoltre il compilatore Swift a verificare che la superclasse della tua classe che esegue l'override (o uno dei suoi genitori) abbia una dichiarazione che corrisponde a quella che hai fornito per l'override. Questa verifica garantisce che la tua definizione di override sia corretta.

### Accedere a metodi, proprietà e subscript della superclasse <a href="#accedere-a-metodi-proprieta-e-subscript-della-superclasse" id="accedere-a-metodi-proprieta-e-subscript-della-superclasse"></a>

Quando fornisci un override di un metodo, di una proprietà o di un subscript per una sottoclasse, a volte è utile usare l'implementazione esistente della superclasse come parte del tuo override. Per esempio, puoi affinare il comportamento di quell'implementazione esistente, o memorizzare un valore modificato in una variabile ereditata esistente.

Quando è opportuno, accedi alla versione della superclasse di un metodo, di una proprietà o di un subscript usando il prefisso `super`:

* Un metodo sovrascritto chiamato `someMethod()` può chiamare la versione della superclasse di `someMethod()` chiamando `super.someMethod()` all'interno dell'implementazione del metodo che esegue l'override.
* Una proprietà sovrascritta chiamata `someProperty` può accedere alla versione della superclasse di `someProperty` come `super.someProperty` all'interno dell'implementazione del getter o del setter che esegue l'override.
* Un subscript sovrascritto per `someIndex` può accedere alla versione della superclasse dello stesso subscript come `super[someIndex]` dall'interno dell'implementazione del subscript che esegue l'override.

### Override dei metodi <a href="#override-dei-metodi" id="override-dei-metodi"></a>

Puoi sovrascrivere un metodo di istanza o di tipo ereditato per fornire un'implementazione su misura o alternativa del metodo all'interno della tua sottoclasse.

L'esempio seguente definisce una nuova sottoclasse di `Vehicle` chiamata `Train`, che sovrascrive il metodo `makeNoise()` che `Train` eredita da `Vehicle`:

```swift
class Train: Vehicle {
    override func makeNoise() {
        print("Choo Choo")
    }
}
```

Se crei una nuova istanza di `Train` e chiami il suo metodo `makeNoise()`, puoi vedere che viene chiamata la versione del metodo della sottoclasse `Train`:

```swift
let train = Train()
train.makeNoise()
// Stampa "Choo Choo".
```

### Override delle proprietà <a href="#override-delle-proprieta" id="override-delle-proprieta"></a>

Puoi sovrascrivere una proprietà di istanza o di tipo ereditata per fornire un tuo getter e un tuo setter personalizzati per quella proprietà, o per aggiungere osservatori di proprietà che permettano alla proprietà che esegue l'override di osservare quando il valore della proprietà sottostante cambia.

#### Override di getter e setter delle proprietà <a href="#override-di-getter-e-setter-delle-proprieta" id="override-di-getter-e-setter-delle-proprieta"></a>

Puoi fornire un getter personalizzato (e un setter, se opportuno) per sovrascrivere *qualsiasi* proprietà ereditata, indipendentemente dal fatto che la proprietà ereditata sia implementata all'origine come proprietà memorizzata o calcolata. La natura memorizzata o calcolata di una proprietà ereditata non è nota a una sottoclasse — questa sa soltanto che la proprietà ereditata ha un certo nome e un certo tipo. Devi sempre dichiarare sia il nome sia il tipo della proprietà che stai sovrascrivendo, per permettere al compilatore di verificare che il tuo override corrisponda a una proprietà della superclasse con lo stesso nome e lo stesso tipo.

Puoi presentare una proprietà ereditata di sola lettura come proprietà di lettura e scrittura fornendo sia un getter sia un setter nell'override della proprietà nella tua sottoclasse. Non puoi, però, presentare una proprietà ereditata di lettura e scrittura come proprietà di sola lettura.

{% hint style="info" %}
**Nota:** Se fornisci un setter come parte dell'override di una proprietà, devi fornire anche un getter per quell'override. Se non vuoi modificare il valore della proprietà ereditata all'interno del getter che esegue l'override, puoi semplicemente far passare il valore ereditato restituendo `super.someProperty` dal getter, dove `someProperty` è il nome della proprietà che stai sovrascrivendo.
{% endhint %}

L'esempio seguente definisce una nuova classe chiamata `Car`, che è una sottoclasse di `Vehicle`. La classe `Car` introduce una nuova proprietà memorizzata chiamata `gear`, con un valore intero predefinito di `1`. La classe `Car` sovrascrive anche la proprietà `description` che eredita da `Vehicle`, per fornire una descrizione personalizzata che include la marcia corrente:

```swift
class Car: Vehicle {
    var gear = 1
    override var description: String {
        return super.description + " in gear \(gear)"
    }
}
```

L'override della proprietà `description` inizia chiamando `super.description`, che restituisce la proprietà `description` della classe `Vehicle`. La versione di `description` della classe `Car` aggiunge poi del testo extra alla fine di questa descrizione per fornire informazioni sulla marcia corrente.

Se crei un'istanza della classe `Car` e imposti le sue proprietà `gear` e `currentSpeed`, puoi vedere che la sua proprietà `description` restituisce la descrizione su misura definita all'interno della classe `Car`:

```swift
let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: \(car.description)")
// Car: traveling at 25.0 miles per hour in gear 3
```

#### Override degli osservatori di proprietà <a href="#override-degli-osservatori-di-proprieta" id="override-degli-osservatori-di-proprieta"></a>

Puoi usare l'override delle proprietà per aggiungere osservatori di proprietà a una proprietà ereditata. Questo ti permette di ricevere una notifica quando il valore di una proprietà ereditata cambia, indipendentemente da come quella proprietà sia stata originariamente implementata. Per maggiori informazioni sugli osservatori di proprietà, vedi [Osservatori di proprietà](/guida-al-linguaggio/proprieta.md#osservatori-di-proprieta).

{% hint style="info" %}
**Nota:** Non puoi aggiungere osservatori di proprietà a proprietà memorizzate costanti ereditate o a proprietà calcolate di sola lettura ereditate. Il valore di queste proprietà non può essere impostato, e quindi non è appropriato fornire un'implementazione di `willSet` o `didSet` come parte di un override.

Nota inoltre che non puoi fornire sia un setter di override sia un osservatore di proprietà di override per la stessa proprietà. Se vuoi osservare le modifiche al valore di una proprietà, e stai già fornendo un setter personalizzato per quella proprietà, puoi semplicemente osservare qualsiasi modifica del valore dall'interno del setter personalizzato.
{% endhint %}

L'esempio seguente definisce una nuova classe chiamata `AutomaticCar`, che è una sottoclasse di `Car`. La classe `AutomaticCar` rappresenta un'auto con cambio automatico, che seleziona automaticamente una marcia appropriata da usare in base alla velocità corrente:

```swift
class AutomaticCar: Car {
    override var currentSpeed: Double {
        didSet {
            gear = Int(currentSpeed / 10.0) + 1
        }
    }
}
```

Ogni volta che imposti la proprietà `currentSpeed` di un'istanza di `AutomaticCar`, l'osservatore `didSet` della proprietà imposta la proprietà `gear` dell'istanza su una marcia appropriata per la nuova velocità. In particolare, l'osservatore di proprietà sceglie una marcia pari al nuovo valore di `currentSpeed` diviso per `10`, arrotondato per difetto all'intero più vicino, più `1`. Una velocità di `35.0` produce una marcia pari a `4`:

```swift
let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4
```

## Impedire gli override <a href="#impedire-gli-override" id="impedire-gli-override"></a>

Puoi impedire che un metodo, una proprietà o un subscript vengano sovrascritti contrassegnandoli come *final*. Per farlo, scrivi il modificatore `final` prima della parola chiave introduttiva del metodo, della proprietà o del subscript (come `final var`, `final func`, `final class func` e `final subscript`).

Qualsiasi tentativo di sovrascrivere un metodo, una proprietà o un subscript final in una sottoclasse viene segnalato come errore in fase di compilazione. Anche i metodi, le proprietà o i subscript che aggiungi a una classe in un'estensione possono essere contrassegnati come final all'interno della definizione dell'estensione. Per maggiori informazioni, vedi [Estensioni](/guida-al-linguaggio/estensioni.md).

Puoi contrassegnare un'intera classe come final scrivendo il modificatore `final` prima della parola chiave `class` nella sua definizione di classe (`final class`). Qualsiasi tentativo di creare una sottoclasse di una classe final viene segnalato come errore in fase di compilazione.
