Compatibile con Xcode 8

Programmazione ad oggetti in Swift

Uno dei paradigmi di sviluppo più affascinanti degli ultimi anni, ultimi anni si fa per dire, è la programmazione ad oggetti.

Un paradigma è un insieme di regole che ti guidano verso la programmazione e sviluppo di un software o applicazione. Grazie alla programmazione ad oggetti ti troverai a vedere il codice e le applicazioni tutte da un’altra prospettiva. Se capita fino in fondo, la programmazione ad oggetti, ha effetti sul modo di pensare e interpretare il mondo che ti circonda.

La programmazione ad oggetti è filosofia, pura astrazione.

Grazie alla programmazione ad oggetti del linguaggio Swift arriverai agli stessi concetti che ti porteranno a sviluppare la tua prima applicazione. Già da questa lezione, puoi cominciare a dare uno sguardo al mio prossimo corso o ai tutorial sul blog.

Anche se la programmazione ad oggetti in Swift è decisamente semplificata rispetto agli altri linguaggi, partiamo dal principio e rispondiamo a queste semplici domande.

Perché è stata chiamata ad oggetti? e cos’è un oggetto?

Cos’è un oggetto in un linguaggio di programmazione

Ogni cosa è un oggetto. il MacBook da cui ti sto scrivendo, la cotoletta che hai mangiato a pranzo, la penna stilo con cui scrivi e persino il tuo migliore amico è un oggetto.

Ma, cosa rende qualcosa un oggetto?

Un oggetto è un’entità che può essere identificata da delle proprietà specifiche. Per proprietà intendo sia i suoi attributi che le sue funzionalità.

Ognuno di questi bellissimi Husky ha degli attributi unici che l’altro non ha. Il colore del pelo, il peso, il nome, il colore degli occhi e così via. Ognuno ha anche delle funzionalità diverse rispetto al vicino. Uno corre in un modo, l’altro ulula in modo diverso…

Cioè un oggetto è qualcosa che puoi categorizzare mediante delle proprietà (inteso come caratteristiche). Una penna sai che è una penna perché ha quella particolare forma e funzionalità. Un cane sai che è diverso da un gatto perché abbaia e sicuramente non miagola.

Ti faccio un altro esempio, io (Giuseppe) sono un oggetto caratterizzato dagli attributi: data di nascita, colore della pelle, altezza, QI, colore capelli e chi più ne ha più ne metta. Inoltre ho delle funzionalità: posso camminare, saltare, studiare ecc ecc.

Lo scopo della programmazione ad oggetti con il linguaggio Swift è quello di permettere, ad uno sviluppatore, di poter raffigurare oggetti e comportamenti informatici con lo stesso sistema che utilizziamo noi essere umani quando descriviamo la realtà che ci circonda.

Due oggetti simili, come me e Matteo che siamo entrambe Persone e quindi caratterizzati dagli stessi attributi, siamo diversi perché possediamo dei valori non uguali che caratterizzano i nostri attributi. Io sono nato giorno x e lui giorno y, io sono alto 1 e lui 2.

Adesso puoi dedurre che i valore assunti dagli attributi definiscono lo stato dell’oggetto. Quindi due oggetti, apparentemente simili, sono diversi quando hanno uno stato diverso.

La classe, il modello astratto di un oggetto

Nell’ipotetico caso in cui tu non avessi conosciuto la razza Husky, cos’è che avresti detto guardando quella foto? Sicuramente avresti detto: “Ma che bellini quei cagnolini”.

Perché sei andato sul sicuro dicendo che quelli sono cani?

Perché sai che i cani, pur essendo diversi in razze, hanno tutti la stessa fisionomia e caratteristiche.

Cioè sai per certo che hanno un pelo, delle zampe, che abbaiano ecc. E, di conseguenza, in base al valore reale di quelle caratteristiche sai se un cane appartiene ad una razza o un’altra. Un Pastore Tedesco è diverso da un Husky ma entrambi sono comunque Cani.

Oppure, io e tu siamo per certo delle persone, e non dei cani (qualcuno lo è, ndr), perché abbiamo degli attributi e funzionalità che ci rendono diversi da loro.

Però, io e te, siamo comunque diversi perché abbiamo valori diversi. Io sono alto x, tu y. Io ho i capelli scuri, tu x e così via.

A questo punto, introduciamo un nuovo elemento.

Gli oggetti con le stesse proprietà fanno parte della stessa categoria. Queste categorie prendono il nome di Classi.

  1. Una Classe è il modello astratto di un oggetto, uno schema che rappresenta in modo concettuale un oggetto.
  2. La rappresentazione reale della classe, che chiamerai istanza della classe, prende il nome di oggetto.

Attenzione! Dire Oggetto e dire Classe non equivale a dire la stessa cosa! (Cosa che purtroppo si sente dire).

Matteo è l’istanza, quindi un oggetto, della classe Persona, Greg (il mio cane) è l’istanza della classe Cane, il MacBook è un oggetto della classe Portatile e così via.

É la classe a definire gli attributi e le funzionalità di un oggetto. Quest’ultimo, essendo un’istanza della classe, ne eredita tutte le proprietà.

differenza-tra-classe-ed-oggetto-linguaggio-swift

Creare una Classe con il linguaggio Swift

Ripetere le cose non fa mai male.

Una classe è la rappresentazione astratta di un oggetto, ne definisce le proprietà e il comportamento (funzionalità).

Con il linguaggio Swift, la rappresentazione di una classe è fatta precedere dalla parola chiave class seguito dal nome e dalle parentesi graffe:

Le regole del buon programmatore impongono che la prima lettera del nome della classe sia scritta in Maiuscolo.

Proviamo a creare una semplice classe per poter descrivere un Cane. Come proprietà definire solamente la razza, il colore ed il peso.

Le proprietà della classe, come puoi notare, sono delle semplicissime variabili (o costanti) che ci permetteranno di descrivere l’oggetto con dei valori.

Abbiamo semplicemente definito in maniera ideale quali sono le proprietà di un Cane qualsiasi. Non abbiamo messo dei valori di default perché, come dicevamo, ogni oggetto ha i suoi valori unici. Questo è il motivo per cui ho lasciato le proprietà opzionali.

Adesso che hai definito la classe Cane è arrivato il momento di creare degli oggetti Cane reali.

Istanziare una classe. Il processo di creazione di un oggetto

Quando nasce un bambino gli viene assegnato un nome. Si registra il peso di nascita, si vede di che colore ha i capelli e cose di questo genere.

Ti ho detto poc’anzi che la classe descrive in maniera generale e ipotetica una tipologia d’oggetti ma non da i valori reali di quell’oggetto perché ogni oggetto è unico.

Si sono appena conclusi i fatidici nove mesi!! Sei diventato papà/mamma!!

Come faccio a creare un oggetto della classe Persona?

Init e la costruzione dell’oggetto

Qui entra in gioco il costruttore. Il costruttore è una funzione particolare che serve, per l’appunto, a definire quali saranno i valori reali da dare all’oggetto al momento della sua creazione.

Il costruttore o init è una funzione del linguaggio Swift a tutti gli effetti. Come parametri si mettono gli stessi attributi della classe che si vorranno inizializzare quando si creerà l’oggetto.

Dentro la funzione init dovrai passare i valori, che l’utente metterà nei parametri, alle proprietà della classe:

A questo punto, quando dovrai creare un nuovo oggetto Persona (perché è nato il famoso bimbo) potrai utilizzare la sintassi NomeClasse.init(<parametri>):

Finalmente hai creato dei nuovi oggetti figli della classe Persona. Come lo hai fatto? mediante l’utilizzo della funzione speciale init che serve, per l’appunto, a creare un nuovo oggetto della classe su cui viene utilizzato.

init-e-costruzione-oggetto-linguaggio-swift

Accedere alle proprietà della classe

A questo punto hai tre nuovi oggetti di tipo Persona. Nel caso in cui volessi leggere i valori delle loro proprietà, potrai farlo utilizzando la notazione nomeOggetto.nomeProprietà. Per esempio, se volessimo leggere i nomi dei tre oggetti, scriverei:

programmazione ad oggetti linguaggio swift

Init senza parametri

Una classe può essere costruita anche con un init senza parametri solo se le sue proprietà sono opzionali oppure hanno dei valori di default.

Le classe che hanno questa caratteristica possono usare un init() presente di default.

Grazie a questo init vuoto puoi istanziare le proprietà dell’oggetto in un secondo momento.

Nell’esempio ho creato l’oggetto nuovaPersona e successivamente ho dato dei valori alle sue proprietà. Questo caso può essere utile quando, in un’applicazione, vuoi dare i valori di un oggetto solamente dopo determinati passaggi.

Nel caso in cui fosse presente un init all’interno della classe, l’init senza parametri non potrà più essere utilizzato:

Proprietà opzionali o no?

Quando abbiamo definito la classe Persona abbiamo anche messo tre proprietà: nomepeso colore_capelli. Queste tre proprietà le abbiamo anche messe opzionali perché, come ti dicevo, non possiamo definire a priori un valore di default per queste proprietà.

Ovvero, dato che non tutte le persone hanno lo stesso nome, lo stesso peso ecc, l’opzionalità ci da modo di evitare l’assegnazione di un valore.

C’è una regola da rispettare.

Le proprietà della classe, se non sono opzionali, devono essere tutte inizializzate alla costruzione dell’oggetto (cioè quando si usa la funzione init).

Facciamo un esempio.

La nostra applicazione gestisce una fattoria con delle Mucche. Ogni mucca deve avere un codice numerico che la identifica. Però non vogliamo lasciarlo opzionale questo valore perché non deve essere più modificato. Quindi ci serve una costante.

Vedrai che il Playground ti avviserà di un errore.

schermata-2016-10-24-alle-17-49-49

L’errore di comunica che non puoi lasciare le proprietà della classe senza valori di default, opzionalità o senza che un init le riempia.

Lui ti consiglia di mettere un valore di default, cioè una stringa vuota “”. Io ti consiglio, dato anche che l’esercizio chiedeva questo, di mettere un init con un parametro:

A questo punto è facile dedurre che:

  1. Le proprietà che ti servono obbligatoriamente alla creazione dell’oggetto vadano messe non opzionali (salvo alcuni casi), perché l’init ti assicurerà che lì ci sarà sempre un valore.
  2. Mentre quelle che non ti servono subito le puoi lasciare opzionali.
condividi xcoding

Ho impiegato un po’ di tempo a scrivere questo tutorial. Se ti va, ricambia il mio lavoro, con un like alle mie pagine!

[addtoany]

Grazie ;)

Classe come nuovo Tipo di Dato

Quando crei una classe, in realtà, stai creando anche un nuovo Tipo di Dato. Cioè come i Tipi di Dato che già hai incontrato (String, Double ecc – loro in realtà non sono delle classi) anche le classi ti permettono di definire il tipo ad una variabile.

In questo semplice esempio ho definito un array di tipo [Mucca] cioè potrà contenere oggetti istanza della classe Mucca. In più, alle variabili muccaPippo e muccaGino ho definito in maniera esplicita il tipo di dato anche se non era strettamente necessario dato che già l’inizializzazione dell’oggetto gli assegna il tipo di dato Mucca.

Ad ogni modo è sempre una buona norma definire esplicitamente il tipo di dato quando si conosce a priori.

Metodi di una Classe con il linguaggio Swift

Un oggetto, come ribadito ad inizio lezione, può eseguire delle azioni. Camminare, mangiare, bere, correre, uccidere. Sono tutte azioni che accomunano o contraddistinguono gli oggetti.

Un cane abbaia, mentre un gatto miagola. Sono azioni simili, per certi versi, ma diverse nell’azione finale.

Le azioni, con il linguaggio Swift, vengono definite mediante le funzioni. Una classe può avere delle funzioni che permettono di far compiere delle azioni ad un oggetto.

Le azioni o funzioni, per un oggetto, prendono il nome di metodi.

Prendiamo sempre l’ultima classe creata. Quella della Mucca. Potremmo creare un metodo, cioè una funzione, che ci permetta di stampare la quantità di latte che ha prodotto. La chiameremo stampaQuantitàLatte e inseriremo un print della proprietà codice e della proprietà latteProdotto.

Quando vorrai utilizzare il metodo potrai farlo mediante la notazione nomeOggetto.nomeMetodo() come una semplicissima funzione. Solo che, questa volta, la funzione partirà direttamente dall’oggetto.

La cosa interessante è che i metodi interagiscono solo con le proprietà dell’oggetto che le invoca. Se creassi un’altra mucca, con una sua quantità di latte ed un codice, il metodo stamperà ovviamente solo i suoi valori perché devi pensare ad un oggetto come ad un’entità a se stante.

Metodi e parametri

Anche i metodi, come le normali funzioni, possono avere dei parametri.

Nel nostro esempio, potremmo creare un metodo che aggiunge una nuova quantità di latte alla proprietà latteProdotto.

Nel metodo aggiungiQuantitàLatte ho messo, prima di aggiungere la nuovaQuantità al latteProdotto, un controllo sulla presenza o meno di un valore nella proprietà latteProdotto dato che è opzionale. Successivamente ho aggiunto alla quantitàPresente la nuovaQuantità:

La parola chiave self

Diamo uno sguardo a questa semplice classe:

I parametri del costruttore init sono uguali, come sintassi, a quelli delle proprietà della classe.

Se adesso tu provassi ad assegnare il valore dei parametri ai valori delle proprietà della classe, noteresti il nascere di un errore perché i nomi sono uguali ed il compilatore non sa di preciso a quale ti stai riferendo.

Per evitare il nascere di questi problemi, è stata creata una parola chiave che ti permette di riferirti alle proprietà o metodi della classe in cui ti trovi.

La parola chiave si chiama self e ti permette di accedere solo alle proprietà e metodi della classe. Grazie al self sei in grado di risolvere questo piccolo problema.

Il self non serve solamente a questo scopo. Nel caso di progetti più vasti e articolati, utilizzare la parola chiave self ti fa subito capire che quella cosa che lo segue appartiene alla classe e non viene da un’altra parte del codice.

Il mio consiglio è di utilizzare la parola chiave self sempre. Se stai modificando o utilizzando le proprietà o metodi della classe, utilizza sempre il self. In questo modo, quando andrai a ricontrollare il codice, capirai subito che quella proprietà/metodo la devi andare a cercare dentro la classe e non altrove.

A cosa serve la programmazione ad oggetti?

Fatto questo lungo excursus su come scrivere correttamente una semplice Classe è arrivato il momento di capire realmente a cosa servono.

Il motivo della loro nascita è abbastanza semplice. Si chiama semplificazione del codice e dei processi di sviluppo di un’applicazione.

Ma peppe, io tutta questa semplificazione non la sto vedendo, puoi essere più chiaro?

Per farti capire meglio l’utilizzo della programmazione ad oggetti con il linguaggio Swift, ti voglio fare dei semplici esempi di utilizzo reale.

Esempio 1. Applicazione per la gestione della lista della spesa

Hai una semplice applicazione che ti permette di salvare gli alimenti che devi acquistare al supermercato. Ogni cosa da acquistare è caratterizzata dalla categoria d’appartenenza (Dolci, Carne, Altro ecc) e dal nome dell’oggetto da comprare.

L’applicazione deve essere in grado di salvare tutti questi oggetti da comprare dentro una lista e di toglierli dalla lista per metterli nella lista dei già acquistati.

Vediamo un po’ come strutturare il progetto.

Hai bisogno di un qualcosa che ti descriva questi oggetti da comprare. A tal proposito puoi creare una classe, chiamata OggettoSpesa, formata dalle proprietà categoria e nome.

In questo modo, quando l’utente riempirà due campi di testo per definire la categoria ed il nome dell’oggetto da acquistare, l’applicazione creerà un nuovo OggettoSpesa.

Senza la classe avresti avuto sicuramente delle variabili sparse e non collegate logicamente, oppure delle tuple che a lungo andare avrebbero confuso di tantissimo il progetto.

Adesso ci serve un contenitore dove poter mettere questi oggetti da acquistare.

Potremmo creare un ulteriore oggetto che ci permetta di gestire una lista di oggetti da acquistare ed una lista di oggetti acquistati. Cioè, invece di avere dei semplici array sparsi nel codice come questi:

Li metteremo all’interno di una classe chiamata GestoreListaSpesa che ci permetterà di interagire in maniera semplificata con questi array:

Qui arriva il bello della programmazione ad oggetti. La complessità del progetto adesso si sposta tutta dentro la classe.

Potremmo creare un metodo della classe che ci permetta di poter aggiungere il nuovo oggetto alla lista oggettiDaAcquistare:

In modo tale che quando si utilizzerà, verrà più semplice ed immediato l’inserimento dell’oggetto da acquistare nella lista opportuna:

Idem per la rimozione dell’oggetto dalla lista. Puoi creare un nuovo metodo che, dato l’inserimento del nome dell’oggetto acquistato, rimuova l’elemento dall’array e lo passi all’interno dell’array oggettiAcquistati. Aggiungi il seguente metodo alla classe GestoreListaSpesa:

Il codice trova l’elemento nella lista degli oggettiDaAcquistare, lo aggiunge agli oggettiAcquistati ed infine rimuove l’elemento dall’array oggettiDaAcquistare (con la funzione .remove(at: Int) che vuole l’indice della posizione dell’elemento nell’array).

[su_spoiler title=”Tutto il Codice dell’esercizio” style=”fancy”] [/su_spoiler]

Esempio 2. Una rubrica telefonica

Immagina di dover creare la rubrica telefonica dei tuoi contatti ed un sistema per poter chiamare i contatti presenti. Da cosa potrebbe essere composta?

Sicuramente i contatti della rubrica possono essere identificati da un nome ed un numero di telefono. Quindi la rubrica non è altro che una collezione di contatti.

La rubrica inoltre deve possedere dei metodi che permettono di chiamare uno dei contatti presenti nella sua lista.

Il procedimento è sempre quello spiegato nella lezione delle funzioni. Ovvero bisogna utilizzare il paradigma Divide et Impera. In questo caso, però, invece di avere più funzioni abbiamo classi che distinguono cose ben specifiche.

Una sarà la classe Contatti composta dal nome e dal numero della persona e l’altra sarà la classe Rubrica che conterrà tutti i contatti e permetterà di chiamarne uno della lista.

Ho definito la classe Contatto con due attributi, nome e numero. Il costruttore, o metodi init, inizializzerà un oggetto contatto solo ed esclusivamente se sono stati inseriti i due parametri. Mentre la classe Rubrica non è altro che un contenitore di oggetti Contatto.

Da notare che, come già detto sopra, anche le classi creano un nuovo tipo di dato che è possibile utilizzare alla stregue dei tipi fondamentali. Infatti la lista contatti ha come tipo di dato [Contatto] ovvero è un array di tipo Contatto.

Adesso devi inserire il metodo per chiamare, ipoteticamente, un contatto della lista. Per semplificare alcuni passaggi, potremmo creare anche il metodo di inserimento di un nuovo contatto in lista. In questo modo deleghiamo all’oggetto tutte le fasi di gestione:

La funzioni, o metodo, aggiungiContatto(new:) fa un semplice append all’array contatti.

Il metodo chiama(nome:) restituisce un Bool con il risultato della chiamata. True se effettuata e false altrimenti. La prima parte del metodo è un controllo sulla presenza o meno di elementi nell’array dei contatti. La funzione guard è stata introdotta con Swift 2.0 e ti invito ad adottarla anche tu nel tuo codice, puoi aggiornarti seguendo questa lezione: istruzione Guard in Swift.

Infine, il metodo, cicla tutta la lista alla ricerca del contatto da chiamare, se lo trova lo chiama e restituisce true.

Lascio a te il compito di creare gli oggetti e popolare la Rubrica.

Linee guida per una buona programmazione ad oggetti

Il nome di una classe comincia sempre con la Prima lettera Maiuscola. Questa è una delle regole più importanti della programmazione ad oggetti.

Perché? In questa maniera eviti di generare confusione tra ciò che è oggetto e ciò che non lo è, ad esempio:

Una classe deve essere unica nel suo genere. Ovvero due classi non possono avere le stesse proprietà e funzionalità:

Chi è il cane è chi è il gatto? Questo pseudo errore lo risolverai nella prossima lezione.

  1. Le proprietà di una classe devono esclusivamente riferirsi all’argomento per cui è stata creata la classe.
    1. La classe Musica non può avere come attributo una variabile Carne perché non avrebbe molto senso.
    2. Le classi devono essere qualcosa di generale o di estremamente preciso, vie di mezzo non possono esisterne.
  2. Meglio creare molte classi rispetto a crearne una che ha al suo interno molte cose diverse.

Più andrai avanti più si aggiungeranno consigli alla seguente lista.

Considerazioni

Se stai affrontando per la prima volta questo argomento potresti essere più confuso che persuaso.

Entrare nell’ottica che tutto è rappresentabile tramite una classe è che tutto quello che ci circonda non è altro che un mucchio di oggetti mi rendo conto che è abbastanza difficile.

Dalle prossime lezioni inizierai a comprendere meglio il potere della programmazione ad oggetti in Swift e se sei arrivato fin qua sotto sei sulla buona strada.

Nella prossima lezione analizzerai nel dettaglio come personalizzare i metodi e proprietà di una classe.

Esercizi da svolgere

Se ti fa piacere di condividerli, o nel caso avessi avuto dei problemi, lascia pure un commento.

  • Esercizio 1. Una Fattoria ha diversi animali: galline, mucche, cavalli. Ogni animale ha un peso, un prezzo (diverso per ogni animale) ed un codice identificativo (anche questo diverso). Gli animali sono gestiti da un gestore, chiamiamolo Fattoria. La Fattoria deve essere in grado di:
    • Stampare il numero degli animali per categoria. Esempio: “Ci sono 4 galline, 4 mucche e 2 cavalli”.
    • Stampare il valore totale della fattoria. Cioè devi sommare il prezzo di tutti gli animali.
    • Vendere un animale. Dato il codice identificativo dell’animale, lo deve cercare all’interno dell’array ed eliminare.
    • Come suggerimento: Crea un array per ogni tipo di animale.
  • Esercizio 2. Similmente a quanto fatto per l’esercizio della Rubrica, prova a creare un sistema che permetta di gestire una classifica di utenti di un gioco. Gli utenti sono caratterizzati da un nome ed un punteggio. Il gestore dei player deve cercare il giocatore con punteggio maggiore e stampare il suo nome e punteggio.

Buona Programmazione!

Changelog

  • 25/10/2016 – Aggiunto il changelog. Modifiche sostanziali al testo e compatibilità con Xcode 8 e linguaggio swift 3.0.

Torna a: Corso gratuito linguaggio di programmazione Swift > Programmazione ad oggetti in Swift

Start typing and press Enter to search

Le funzioni in Swiftenum in swift