Home Testo Corso Swift Classi – Ereditarietà

Classi – Ereditarietà

450
0
Classi Swift

In questa lezione continuiamo a parlare delle Classi nello specifico vedremo l’ereditarietà di una classe.

Nelle lezioni precedenti abbiamo visto a livello teorico cosa è una classe, un oggetto e l’istanza della classe. Abbiamo visto poi come creare una classe in Swift, i relativi attributi, come gestirli tramite l’Opzionalità e i costruttori, abbiamo visto i metodi di una classe, come utilizzare una classe come tipo di dato e il get e set di una proprietà.

Ti ho detto fin dal principio di questo corso che devi fin da subito imparare a programmare nel modo più semplice e funzionale possibile, sia per rendere le tue future applicazioni più veloci sia per rendere meno oneroso il compito futuro di manutenzione del codice stesso tramite l’utilizzo accurato delle variabili, funzioni, classi.

Per quando riguarda le classi ti ho detto che devi cercare di rendere ogni classe più generica e indipendente possibile così da poterla utilizzare in più contesti e applicazioni.

Se per esempio avessi la necessità di dovere creare un programma per la gestione di un archivio di dati di uomini e donne. La prima idea che potrebbe venirti in mente è creare 2 classi diverse una per le donne e una per gli uomini.

// --------------------  Classe Uomo  ---------------

class Uomo {
    
    var nome: String
    var cognome: String
    var altezza: Double
    var eta: Int
      
    // Proprietà uniche Uomo
    
    init(nome: String, cognome:String, altezza: Double, eta: Int) {
        
        self.nome = nome
        self.cognome = cognome
        self.altezza = altezza
        self.eta = eta
    }
}

// --------------------  Classe Donna  ---------------

class Donna {
    
    var nome: String
    var cognome: String
    var altezza: Double
    var eta: Int
        
    // Proprietà uniche Donna
    // Gravidanza, valori analisi ecc ecc
      
    init(nome: String, cognome:String, altezza: Double, eta: Int) {
        
        self.nome = nome
        self.cognome = cognome
        self.altezza = altezza
        self.eta = eta
    }
}

Nell’esempio, puoi notare che entrambi le classi hanno degli attributi in comune, nome, cognome, altezza, età…. e altre differenti tipo gravidanza, valori clinici….

Quindi potremmo porci la domanda, Esiste un modo per accomunare più classi e contemporaneamente distinguerle tra loro?

Nel caso della classe Uomo e della classe Donna, potremmo dire che entrambe potrebbero prendere delle proprietà da un’ipotetica classe generica chiamata Persona.

Con la programmazione ad oggetti sarai in grado di poter definire una o più classi come discendenti da una classe più generica. Cioè proprio come nella realtà, anche le classi potranno essere definite a partire da un modello generico.

Questa caratteristica della programmazione OOP (Object Oriented Programming) prende il nome di EreditarietàL’Ereditarietà permette di creare classi, partendo da una classe più generica, facendoti evitare di dover riscrivere codice ridondante in classi diverse.

Quindi la soluzione consiste nel creare una classe, detta padre o super, che racchiude gli attributi e metodi comuni a tutti gli oggetti di una categoria e tante classe figlie che, ereditano le caratteristiche e contemporaneamente aggiungono quelle caratteristiche che le contraddistingue dal padre e dagli altri fratelli.

Quindi, tornando all’esempio potresti creare la classe Padre o Superclasse Persona che racchiude tutte le caratteristiche comuni, successivamente creare 2 classi figlie o Sottoclasse una per le donne e una per gli uomini.

Una sottoclassesubclass eredita tutti i metodi e attributi, in più può aggiungerne di nuovi e modificare o implementare quelli esistenti.

// --------------  Classe Padre o Superclasse Persona  --------------

class Persona{
    
    var nome: String
    var cognome: String
    var altezza: Double
    var eta: Int
    
    init(nome: String, cognome: String, altezza: Double, eta: Int){
        
        self.nome = nome
        self.cognome = cognome
        self.altezza = altezza
        self.eta = eta
    }
    
    func stampaDati(){
    
        print("Nome: \(self.nome)")
        print("Cognome: \(self.cognome)")
        print("Altezza: \(self.altezza)")
        print("eta: \(self.eta)")        
    }
}

// ------------  Classe Figlie o Sottoclasse di Persona  ----------

class Donna: Persona {

    var gravidanza: Bool = false
    
    func StampaGravidanza(gravidanza: Bool){
        
        if gravidanza == false{
        
            print("Gravidanza: NO")
            self.gravidanza = false
        }
        else{
            
            print("Gravidanza: SI")
            self.gravidanza = true
        }
    }
}

var maria = Donna(nome: "Maria", cognome: "Rossi", altezza: 1.67, eta: 34)
maria.stampaDati()
maria.gravidanza = true
maria.StampaGravidanza(gravidanza: true)

Come puoi vedere nell’esempio ho creato 2 classi la prima chiamata Persona dove sono presenti tutti gli attributi generici di una ipotetica persona e e successivamente una classe chiama Donna che è figlia della classe Persona dove al suo interno presenta una proprietà e un metodo.

Ho poi creato una istanza della classe Donna chiamata maria e che come puoi vedere essendo una figlia di persona eredità tutte le proprietà e i metodi della classe padre infatti ho potuto utilizzare il costruttore e il metodo stampaDati della classe padre.

Per rendere una classe figlia di un’altra classe bisogna dopo il nome della classe aggiungere i due punti e il nome della classe padre.

class nomeClasseFiglia : NomeClassePadre{

// Proprietà classe figlia

// Metodi classe figlia
}

Nell’esempio abbiamo visto che la classe Donna essendo una classe figlia di Persona può utilizzare sia gli attributi che i metodi della classe padre ma però possiamo utilizzarli così come impostate dal padre ma se volessimo modificare il comportamento di un metodo non potremmo farlo. Ecco che qui ci viene in aiuto la parola chiave override che ci permette di modificare totalmente il comportamento del metodo del padre.

// ------  Classe Figlie o Sottoclasse di Persona con override  ---------------

class Donna3: Persona {
    
    var gravidanza: Bool = false
       
   override func stampaDati() {
    
        print("Nome: \(self.nome)")
        print("Cognome: \(self.cognome)")
        print("Altezza: \(self.altezza)")
        print("eta: \(self.eta)")

        if gravidanza == false{
            
            print("Gravidanza: NO")
            self.gravidanza = false
        }
        else{
            
            print("Gravidanza: SI")
            self.gravidanza = true
        }       
    }    
}

var carla = Donna3(nome: "Carla", cognome: "Bianchi", altezza: 1.69, eta: 32)
carla.gravidanza = true
carla.stampaDati()

Nell’esempio sopra ho richiamato nella classe figlia il metodo stampaDati della classe padre preceduto dalla key override e ho completamente riscritto il corpo del metodo.

Ora, posso creare un modo più semplice per non dover riscrivere l’intero metodo? Ovviamente la risposta è si.

Posso attraverso la parola chiave super effettuare l’unione degli elementi del metodo del padre con quello della figlia, vediamo come…

class Donna: Persona {
    
    var gravidanza: Bool = false
    
    // Override della classe Padre
    override func stampaDati() {
        // Richiamo la super della classe Padre
        super.stampaDati()
             
        if gravidanza == false{
            
            print("Gravidanza: NO")
            self.gravidanza = false
        }
        else{
            
            print("Gravidanza: SI")
            self.gravidanza = true
        }        
    }    
}

var lucia = Donna(nome: "Lucia", cognome: "Verdi", altezza: 1.56, eta: 65)
lucia.gravidanza = false
lucia.stampaDati()

Nell’esempio ho richiamato nuovamente il metodo stampaDati della classe Padre tramite override ma questa volta invece di riscrivere l’intero metodo ho inserito l’istruzione super.Stampadati().

con questa istruzione gli ho detto al compilatore: Prendi il metodo stampaDati e integralo con le istruzioni sotto.

Quindi ho solo aggiunto le istruzioni che voglio integrare a quelli già presenti nel metodo della classe Padre.

Nel prossimo corso quando inizieremo ha creare le nostre prime applicazioni vedremo che tutti gli strumenti che ci saranno forniti (bottoni, immagini, tabelle ecc) sono gestiti da classi.

Queste classi non potranno essere modificate perché sono conservate all’interno di spazi speciali (chiamati framework) e non sono accessibili direttamente.

L’unico strumento che avremo, per esempio per modificare l’aspetto di un bottone, sarà quello di creare una subclass della classe genitore.

Quindi, capire il significato dell’ereditarietà non è solamente un puro aspetto didattico. Tutto il mondo delle applicazioni gira intorno all’ereditarietà.

Inoltre, l’ereditarietà delle classi, è un modo elegante e funzionale per ottimizzare il codice in vista del riutilizzo in altri progetti e applicazioni.

Per qualunque dubbio o domanda scrivi un commento in questa lezione.