3. Programmazione ad oggetti in Swift Flashcards

1
Q

Programmazione ad oggetti in Swift

A

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?

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Cos’è un oggetto in un linguaggio di programmazione

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

La classe, il modello astratto di un oggetto

A

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.

Una Classe è il modello astratto di un oggetto, uno schema che rappresenta in modo concettuale un oggetto.

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à.

// pseudo codice di una classe

classe Persona {

//attributi

nome

data_nascita

altezza

peso

codice_fiscale

//funzionalità

camminare()

bere()

studiare()

}

//creazione di un’istanza della classe

Giuseppe = Persona()

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Creare una Classe con il linguaggio Swift

A

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:

class UnaClasse {

//proprietà e comportamento

}

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.

class Cane {

//proprietà

var razza: String?

var colore: String?

var peso: Float?

}

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Istanziare una classe. Il processo di creazione di un oggetto

A

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.

class Persona {

var nome: String?

var peso: Double?

var colore_capelli: String?

}

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

Come faccio a creare un oggetto della classe Persona?

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Init e la costruzione dell’oggetto

A

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.

class Persona {

var nome: String?

var peso: Double?

var colore_capelli: String?

init(nuovoNome: String, nuovoPeso: Double, nuovoColoreCapelli: String){

}

}

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

init(nuovoNome: String, nuovoPeso: Double, nuovoColoreCapelli: String) {

nome = nuovoNome

peso = nuovoPeso

colore_capelli = nuovoColoreCapelli

}

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

var giuseppe = Persona.init(nuovoNome: “Giuseppe”, nuovoPeso: 3.55, nuovoColoreCapelli: “neri”)

var delia = Persona.init(nuovoNome: “Delia”, nuovoPeso: 4.2, nuovoColoreCapelli: “castano chiaro”)

var luca = Persona.init(nuovoNome: “Luca”, nuovoPeso: 3.99, nuovoColoreCapelli: “rossi”)

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Accedere alle proprietà della classe

A

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:

giuseppe.nome

delia.nome

luca.nome

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Init senza parametri

A

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.

class Persona {

var nome: String?

var peso: Double?

var colore_capelli: String?

}

var nuovaPersona = Persona.init()

nuovaPersona.nome = “Giuseppe”

nuovaPersona.peso = 65

nuovaPersona.colore_capelli = “neri”

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:

class Persona {

var nome: String?

var peso: Double?

var colore_capelli: String?

init(nuovoNome: String, nuovoPeso: Double, nuovoColoreCapelli: String) {

nome = nuovoNome

peso = nuovoPeso

colore_capelli = nuovoColoreCapelli

}

}

// Errore

var nuovaPersona = Persona.init() // Non puoi utilizzare l’init senza parametri. Utilizza l’init che hai definito nella classe

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Proprietà opzionali o no?

A

Quando abbiamo definito la classe Persona abbiamo anche messo tre proprietà: nome, peso e 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.

class Mucca {

let codice: String

}

Vedrai che il Playground ti avviserà di un errore.

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:

class Mucca {

let codice: String

init(nuovoCodice: String) {

codice = nuovoCodice

}

}

var muccaPippo = Mucca.init(nuovoCodice: “01muccaPippo”)

var muccaGino = Mucca.init(nuovoCodice: “02muccaGino”)

A questo punto è facile dedurre che:

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.

Mentre quelle che non ti servono subito le puoi lasciare opzionali.

class Mucca {

let codice: String

var latteProdotto: Double?

init(nuovoCodice: String) {

codice = nuovoCodice

}

}

var muccaPippo = Mucca.init(nuovoCodice: “01muccaPippo”)

muccaPippo.latteProdotto = 44

print(“mucca (muccaPippo.codice) ha prodotto (muccaPippo.latteProdotto!) litri di latte”)

// mucca 01muccaPippo ha prodotto 44.0 litri di latte

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Classe come nuovo Tipo di Dato

A

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.

class Mucca {}

var stallaMucche: [Mucca] = []

var muccaPippo: Mucca = Mucca.init()

var muccaGino: Mucca = Mucca.init()

stallaMucche.append(muccaPippo)

stallaMucche.append(muccaGino)

print(“nella stalla ci sono (stallaMucche.count) mucche”)

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Metodi di una Classe con il linguaggio Swift

A

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.

class Mucca {

let codice: String

var latteProdotto: Double?

init(nuovoCodice: String) {

codice = nuovoCodice

}

func stampaQuantitàLatte() {

print(“mucca (codice) ha prodotto (latteProdotto) litri di latte”)

}

}

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.

var muccaPippo: Mucca = Mucca.init(nuovoCodice: “01muccaPippo”)

muccaPippo.latteProdotto = 44

muccaPippo.stampaQuantitàLatte()

muccaPippo.latteProdotto = 66

muccaPippo.stampaQuantitàLatte()

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Metodi e parametri

A

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.

class Mucca {

let codice: String

var latteProdotto: Double?

init(nuovoCodice: String) {

codice = nuovoCodice

}

func aggiungiQuantitàLatte(nuovaQuantità: Double) {

guard let quantitàPresente = latteProdotto else {

print(“ancora devi inizializzare la proprietà latteProdotto”)

return

}

latteProdotto! = quantitàPresente + nuovaQuantità

}

func stampaQuantitàLatte() {

print(“mucca (codice) ha prodotto (latteProdotto) litri di latte”)

}

}

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à:

var muccaPippo: Mucca = Mucca.init(nuovoCodice: “01muccaPippo”)

muccaPippo.aggiungiQuantitàLatte(nuovaQuantità: 10)

muccaPippo.latteProdotto = 10

muccaPippo.stampaQuantitàLatte()

muccaPippo.aggiungiQuantitàLatte(nuovaQuantità: 20)

muccaPippo.aggiungiQuantitàLatte(nuovaQuantità: 10)

muccaPippo.stampaQuantitàLatte()

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

La parola chiave self

A

Diamo uno sguardo a questa semplice classe:

class Persona {

var nome: String

var cognome: String

init(nome: String, cognome: String) {

}

}

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.

init(nome: String, cognome: String) {

nome = nome // ERRORE: devo modificare la proprietà o il parametro?

cognome = cognome // ERRORE: devo modificare la proprietà o il parametro?

}

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.

init(nome: String, cognome: String) {

self.nome = nome

self.cognome = cognome

}

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.

class Persona {

var nome: String

var cognome: String

init(nome: String, cognome: String) {

self.nome = nome

self.cognome = cognome

}

func stampaDati() {

print(self.nome)

print(self.cognome)

}

}

var giuseppe: Persona = Persona.init(nome: “Giuseppe”, cognome: “Sapienza”)

giuseppe.stampaDati()

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

A cosa serve la programmazione ad oggetti?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Esempio 1. Applicazione per la gestione della lista della spesa

A

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.

class OggettoSpesa {

var nome: String

var categoria: String

init(nome: String, categoria: String) {

self.nome = nome

self.categoria = 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.

var cotolette: OggettoSpesa = OggettoSpesa.init(nome: “cotolette”, categoria: “Carne”)

var gelato: OggettoSpesa = OggettoSpesa.init(nome: “gelato”, categoria: “Dolci”)

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:

var oggettiDaAcquistare: [OggettoSpesa]

var oggettiAcquistati: [OggettoSpesa]

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

class GestoreListaSpesa {

var oggettiDaAcquistare: [OggettoSpesa]

var oggettiAcquistati: [OggettoSpesa]

init() {

self.oggettiAcquistati = []

self.oggettiDaAcquistare = []

}

}

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:

func aggiungi(oggetto: OggettoSpesa) {

self.oggettiDaAcquistare.append(oggetto)

}

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

let gestoreLista: GestoreListaSpesa = GestoreListaSpesa.init()

var cotolette = OggettoSpesa.init(nome: “cotolette”, categoria: “Carne”)

var gelato = OggettoSpesa.init(nome: “gelato”, categoria: “Dolci”)

gestoreLista.aggiungi(oggetto: cotolette)

gestoreLista.aggiungi(oggetto: gelato)

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:

func rimuovi(nome: String) {

var indice = 0

for elemento in self.oggettiDaAcquistare {

if elemento.nome == nome {

self.oggettiAcquistati.append(elemento)

self.oggettiDaAcquistare.remove(at: indice)

}

indice += 1

}

}

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”]

class OggettoSpesa {

var nome: String

var categoria: String

init(nome: String, categoria: String) {

self.nome = nome

self.categoria = nome

}

}

class GestoreListaSpesa {

var oggettiDaAcquistare: [OggettoSpesa]

var oggettiAcquistati: [OggettoSpesa]

init() {

self.oggettiAcquistati = []

self.oggettiDaAcquistare = []

}

func aggiungi(oggetto: OggettoSpesa) {

self.oggettiDaAcquistare.append(oggetto)

}

func rimuovi(nome: String) {

var indice = 0

for elemento in self.oggettiDaAcquistare {

if elemento.nome == nome {

self.oggettiAcquistati.append(elemento)

self.oggettiDaAcquistare.remove(at: indice)

}

indice += 1

}

}

}

let gestoreLista: GestoreListaSpesa = GestoreListaSpesa.init()

var cotolette = OggettoSpesa.init(nome: “cotolette”, categoria: “Carne”)

var gelato = OggettoSpesa.init(nome: “gelato”, categoria: “Dolci”)

gestoreLista.aggiungi(oggetto: cotolette)

gestoreLista.aggiungi(oggetto: gelato)

gestoreLista.rimuovi(nome: “cotolette”)

print(“hai già acquistato (gestoreLista.oggettiAcquistati.count) oggetti”)

print(“devi ancora acquistare (gestoreLista.oggettiDaAcquistare.count) oggetti”)

[/su_spoiler]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Esempio 2. Una rubrica telefonica

A

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.

class Contatto {

var nome: String

var numero: String

init(nome: String, numero: String) {

self.nome = nome

self.numero = numero

}

}

class Rubrica {

var contatti: [Contatto]

init() {

self.contatti = Contatto

}

}

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:

class Rubrica {

var contatti: [Contatto]

init() {

self.contatti = Contatto

}

func aggiungiContatto(new: Contatto) {

self.contatti.append(new)

}

func chiama(nome: String) -> Bool {

guard self.contatti > 0 else {

print(“prima riempi i contatti”)

return false

}

for x in self.contatti {

if x.nome == nome {

print(“sto chiamando (x.nome) “)

return true

}

}

print(“non ho trovato il contatto (nome)”)

return false

}

}

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.

17
Q

Linee guida per una buona programmazione ad oggetti

A

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:

class Automobile {

var nome: String

init() {

nome = “una auto”

}

}

var Automobile = Automobile()

print(Automobile) // COSA DEVO STAMPARE???

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

class Gatto {

var numeroZampe: Int

var altezza: Int

init() {

numeroZampe = 4

altezza = 0

}

}

class Cane {

var numeroZampe: Int

var altezza: Int

init() {

numeroZampe = 4

altezza = 0

}

}

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

Le proprietà di una classe devono esclusivamente riferirsi all’argomento per cui è stata creata la classe.

La classe Musica non può avere come attributo una variabile Carne perché non avrebbe molto senso.

Le classi devono essere qualcosa di generale o di estremamente preciso, vie di mezzo non possono esisterne.

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.