Type ed Oggetti in Swift
Swift fa parte di una categoria di linguaggi chiamati ad oggetti, i quali a loro volta prendono il nome dal paradigma a cui sono ispirati: Object Oriented programming o OOP.
Non farti spaventare dagli acronimi.
Come esistono lingue a discendenza neolatina o anglosassone, lo stesso vale per i linguaggi di programmazione.
Il paradigma OOP si basa sul concetto di oggetti. Un oggetto è un contenitore di data
(informazioni) e behaviour
(comportamento). Per esempio, Text
o Image
che abbiamo incontrato nel modulo scorso, sono oggetti che ci permettono di rappresentare testi ed immagini sotto forma di codice.
Ovviamente non basta conoscere solamente quali oggetti utilizzare per poter scrivere un programma o applicazione. Sapere che esiste Text
non è di gran aiuto se non sai come usarlo o dove metterlo.
Ed è qui che entrano in gioco conoscere la grammatica e sintassi di un linguaggio.
Grazie alla grammatica, cioè le regole da seguire per comporre delle istruzioni valide, sarai in grado di prendere oggetti da una libreria come SwiftUI e comporli senza dover necessariamente seguire un tutorial.
In questa lezione del corso SwiftUI Tour esploreremo alcuni concetti di programmazione che formano la base di qualsiasi linguaggio ad oggetti come Swift, Kotlin, C#, Typescript etc.
Cominceremo dal capire la differenza tra Type
and Object
, vedremo i type fondamentali del framework Foundation
(tra i quali String
, Int
, Double
, Bool
) ed infine impareremo ad utilizzare le var
e let
.
Let's start!
Type vs Object
Un Type
è il blueprint di un oggetto. Ne definisce il comportamento, le funzioni o metodi con cui potrai interagirci e la tipologia d'informazioni che trasporterà.
Possiamo considerare i type o tipi di dato come la fabbrica da cui provengono i nostri oggetti.
In genere i Type
definiscono tre aspetti di un oggetto:
-
Creazione: definisce i metodi da utilizzare per creare un oggetto e quali parametri, se richiesti, dovrai utilizzare.
Di questa categoria fa parte la keyword
init
.
-
Interazione: definisce quali metodi o funzioni potrai utilizzare per modificare o interagire con l'oggetto creato.
func
è la keyword che ci permetterà di definire il comportamento di un oggetto.
-
Introspezione: definisce delle proprietà che potrai leggere per analizzare il contenuto dell'oggetto.
var
elet
sono le keywords che ci aiuteranno ad accedere e conservare il contenuto di un oggetto.
Se prendiamo come esempio il type Text
abbiamo visto che è una View
in grado di renderizzare graficamente dei testi o String
. Si costruisce passando tra le parentesi tonde un testo virgolettato Text("ciao")
. E può essere modificato utilizzando i modifiers
come font
e fontWeight
:
Text("ciao") // creiamo un oggetto Text con contenuto "ciao"
.font(.title1) // modifichiamo l'oggetto cambiando il font
Text("come stai?") // creazione
.fontWeight(.bold) // interazione
Un oggetto viene anche detto istanza o rappresentazione reale di un
Type
. Nell'esempio diremo che ilText("ciao")
è un oggetto di typeText
.
Ma da dove vengono questi Type
?
Di base il linguaggio di programmazione Swift porta con se diverse librerie di Type
. Una tra queste si chiama Foundation
e potrai utilizzarla, come il nome suggerisce, per creare le fondamenta della tua app.
Se ti ricordi dal modulo precedente, tutti i file in cui abbiamo definito le nostre interfacce cominciamo con un import SwiftUI
.
Ed infatti anche SwiftUI
è una libreria o SDK (Software Development Kit). E contiene tutte le definizioni o type necessari a creare User Interfaces in Swift:
Grazie all'import
potrai utilizzare tutti i Type
pubblici presenti all'interno di una libreria.
Da qui in avanti vedrai che esistono tanti SDK ed ognuno di loro è stato creato per risolvere diversi problemi. Per esempio MapKit
fornisce tutti i type essenziali per interagire con le mappe di sistema.
Per la stragrande maggioranza del corso SwiftUI Tour ci focalizzeremo sui type della libreria o framework Foundation
ed SwiftUI
.
Cominciamo dando uno sguardo a Foundation
.
I Type del Foundation framework
Foundation è il framework che rappresenta la spina dorsale di qualsiasi progetto scritto con il linguaggio Swift.
All'interno del Foundation framework troviamo type essenziali come numeri, testi, collezioni di elementi e type per interagire con servizi di sistema come il calendario ed URL.
Fermiamoci qua con la teoria e passiamo ad un po' di pratica. Comincia aprendo il Playground.
ℹ️ Sei incappato in questa lezione per sbaglio? ho spiegato come si crea un Playground qui. Inoltre, se stai imparando a sviluppare app per iOS, qui trovi tutte le lezioni del corso SwiftUI Tour.
String
Il type String
descrive testi ed operazioni su testi. Un oggetto di tipo String
viene creato in due modi:
Esplicitamente: Scrivendo il nome del type, le parentesi ed il contenuto:
String("contenuto")
Implicitamente: Utilizzando solamente le doppie virgolette.
String("ciao") // Esplicito
String() // Esplicito
"come stai?" // Implicito
Nell'esempio possiamo notare come String()
genera un testo vuoto o equivalente a scrivere ""
.
Int e Double
Il type Int
rappresenta numeri interi positivi o negativi. Mentre il type Double
numeri con virgola.
Come per le String
, anche un Int
e Double
può essere creato esplicitamente o implicitamente:
Int() // 0
Int(10) // Int
-5 // Int
3.0 // Double
Double() // 0.0
Double(-4) // Double
Double(25.0) // Double
Alcune importanti considerazioni:
Int()
eDouble()
generano valori uguali a 0.Le virgole si scrivono utilizzando la notazione anglosassone
.
. Le migliaia non hanno bisogno di,
.Un
Int
è sempre positivo a meno che non aggiungi il-
davanti al numero.Anche se il
Double
ha valore0
dopo la virgola, verrà comunque considerato come oggetto di tipoDouble
.Quando definisci numeri in maniera implicita, in base alla presenza o meno della virgola il sistema deciderà se il type è
Int
oDouble
.
Bool
Un Bool
è un valore che può essere o true
o false
. Viene principalmente utilizzato per rappresentare il risultato di espressioni che possono biforcarsi in base a delle condizioni aritmetiche.
Anche questo può essere definito in maniera esplicita ed implicita.
Bool() // false
Bool(false)
Bool(true)
true
false
Di default un oggetto
Bool()
viene consideratofalse
.
Uguaglianza e comparazione
Adesso che abbiamo aggiungo un po' di foundation Type
nel nostro repertorio, vediamo alcune operazioni che potremo eseguire tra loro.
Tutte le operazioni di eguaglianza generano un oggetto di tipo Bool
che sarà true
o false
in base ai valori comparati. Le operazioni si eseguono con i seguenti simboli:
==
uguale!=
diverso>
o>=
maggiore o maggiore ed uguale<
o<=
minore o minore ed uguale
Vediamo un esempio utilizzando numeri:
2 > 3 // false
2 != 2 // false
2 == 2 // true
2.5 < 5.0 // true
10 >= 10 // true
10 <= 10.1 // true
Le operazioni si leggono da sinistra verso destra. Per esempio: 2 > 3
puoi leggerla come è 2 maggiore di 3?
, il risultato è true
.
Anche gli oggetti di tipo String
possono essere comparati. Ma, a differenza dei numeri, possono ritornare risultati inaspettati. Vediamo qualche esempio:
"a" == "a" // true
"b" != "a" // true
"hello" == "ciao" // false
"peppe" != "luca" // true
"giuseppe" == "Giuseppe" // false
"PEPPE" == "peppe" // false
Nel caso di "PEPPE" == "peppe"
la logica ci dice che sono entrambi uguali ma Swift ci risponde con false
.
Per il linguaggio Swift tutte le operazioni tra String some type sensitive. Minuscole e maiuscole vengono considerati come valori diversi pur rappresentando logicamente lo stesso carattere.
Per quanto riguarda la comparazione, anche qui ci sono alcuni casi da prestare attenzione:
"a" > "b" // false
"b" < "c" // true
"ab" > "c" // false
Nel caso di maggioranza e minoranza le stringhe vengono comparate carattere per carattere. Nell'esempio sopra "ab" > "c"
il risultato è false
perché il primo carattere sulla sinistra, ovvero a
, è minore del primo carattere sulla destra: c
.
Se sei confuso è normale, ti servirà un po' di tempo e pratica per comprendere le eguaglianze di String
. Nella prossima lezione troverai degli esercizi che ti aiuteranno a fissare questi argomenti.
Infine, anche i tipi booleani possono essere comparati.
true == true // true
false != false // false
Type safety
Swift oltre ad essere un linguaggio ad oggetti è anche un linguaggio Type Safe. Ovvero operazioni tra oggetti di tipo eterogeneo sono controllate ed eventualmente considerate errori a compile-time.
Cosa significa?
I Type
oltre a descrivere behaviour e data di un oggetto, definiscono anche quali operazioni sono possibili con oggetti di type diverso.
Per esempio, è considerato un errore sommare String
con Int
:
"2" + 1 // Binary operator '+' cannot be applied to String and Int
Anche sommare Int
con Double
è considerato errore. Infatti, il linguaggio Swift non sa quale type restituire come risultato dell'operazione:
Int(2) + Double(2.5)
Essere un linguaggio type safe significa anche che ogni operazione restituirà un Type
definito nel momento in cui scriviamo il nostro codice.
In questo caso, abbiamo un Int
+ Double
che confonde Swift dato che non sa quale type scegliere come risultato.
Quindi come risolviamo questi problemi?
Il alcuni casi sarà impossibile, in altri ci sono compressi.
Nel caso di Int
+ Double
dobbiamo decidere di convertire uno dei due oggetti nell'altro. Se convertiamo il Double
ad Int
perderemo il valore dopo la virgola, quindi in base al contesto deciderai se conviene convertire Int
a Double
o viceversa:
Int(2) + Int(2.5) // 4
Double(2) + Double(2.5) // 4.5
Lo stesso vale per le String
, possiamo convertire Int
e Double
in modo tale da permettere la somma tra due stringhe:
"1" + String(2) // "12"
Type safety ci aiuta a scrivere codice in maniera sicura, da qui la parola "safety". Infatti, come abbiamo, visto non servirà nemmeno lanciare l'app sul simulatore per capire se abbiamo scritto operazioni tra type non permessi.
Ad ogni modo, type safety non è una proprietà confinata alle operazioni. Vedremo più avanti che utilizzeremo questo termine per definire funzioni, nuovi type e data storage.
Esercizio
Perché la seguente operazione è permessa?
2 + 2.5 // 4.5
Tip: ricordati che alcuni Type vengono definiti in maniera implicita.
init e come si costruiscono gli oggetti in Swift
Per poter creare un oggetto possiamo utilizzare quattro metodi messi a disposizione del linguaggio Swift:
-
Utilizzando la keyword
init
subito dopo il nome di unType
. La sintassi èType.init()
dove all'interno delle parentesi tonde, in base alle specifiche del type in questione, potrai inserire dei parametri o argomenti.init
significa initialiser o costruttore.
Scrivendo
Type()
dove all'interno delle tonde, se richiesto, inserirai i parametri di inizializzazione.Scrivendo
Type { }
dove all'interno delle graffe scriveremo un'espressione/codice che verrà valutata in base al contesto. Un esempio èVStack { Text("hello") }
, spiegheremo un po' meglio questo tipo di costruttori quando imparerai ad usare le funzioni in Swift.-
Utilizzando uno degli oggetti di base o standard di un type utilizzando la sintassi
Type.objectName
doveobjectName
dipenderà dalType
in questione.Per esempio se scrivi
Int.max
stai costruendo un oggettoInt
con il massimo valore rappresentabile.
Userò la parola "argomenti" in maniera intercambiabile con "parametri". In genere, sono i valori che si inseriscono all'interno delle parentesi tonde di un
init
ofunc
.
Durante il modulo scorso e questa lezione hai già costruito parecchi oggetti, adesso stiamo solamente formalizzando la sintassi ed operazione. In questo modo quando incontrerai un Type()
o Type.init
sai che si tratta di un'inizializzazione di un oggetto.
Un modo veloce per capire come si costruisce un oggetto è quello di farsi aiutare da Xcode, infatti se scrivi Type.init
dovrebbe comparire la lista di tutti i costruttori disponibili.
Proviamo un esempio con Text
, all'interno del playground aggiungi import SwiftUI
e poi scrivi Text.init
, dovresti vedere una lista di operazioni permesse:
Se guardiamo il primo init(_ content: StringProtocol)
ci sta dicendo che possiamo inizializzare un oggetto passando all'interno delle parentesi tonde un oggetto di type StringProtocol
.
Nelle lezioni precedenti abbiamo utilizzato implicitamente il primo costruttore che accetta un content
di type StringProtocol
.
String
fa parte della famiglia di type StringProtocol
, quindi ti è permesso scrivere:
Text("ciao")
Text.init("ciao")
// oppure
Text(String("ciao"))
Text.init(String.init("ciao"))
Capiremo meglio cos'è un
Protocol
in una lezione tutta dedicata all'argomento.
Eccezione alla regola
Int
, Double
, String
ed altri type fondamentali del linguaggio Swift sono casi eccezionali perché si possono creare scrivendo direttamente il valore, esempio 3
è equivalente a scrivere Int.init(3)
o Int(3)
.
Vedremo che esisteranno altri due casi come questi che ci permetteranno di definire liste e matrici di oggetti, ma aldilà di questi casi eccezionali, tutti gli oggetti si creano con init
, parentesi tonde o graffe.
Analisi di un init
Analizzare gli init
ed i suoi argomenti ti aiuta a capire come comporre il tuo codice anche senza necessariamente conoscere tutti gli oggetti di un framework.
Per esempio, prendiamo in analisi il costruttore .init(_ date: Date, style: Text.DateStyle)
anche se non sappiamo cosa siano Date
e Date.DateStyle
sappiamo che potremmo costruire un Text
passando un oggetto Date
ed un oggetto DateStyle
:
Possiamo avventurarci nella costruzione di questi due oggetti utilizzando uno dei quattro metodi visti sopra. Il più semplice è provare Type.init
o cercare qualche oggetto di default con Type.
.
Nel caso di Date
usiamo il costruttore vuoto Date()
mentre per Text.DateStyle
vediamo che ci sono degli oggetti di default e nessun init
, prendiamone uno a caso:
import SwiftUI
Text.init(Date.init(), style: Text.DateStyle.date)
Et voilà, anche senza conoscere Date
e Text.DateStyle
siamo riusciti a costruire un oggetto Text
.
Proviamo adesso a visualizzare il contenuto del Text
dentro il playground utilizzando la setLiveView
vista nella lezione precedente:
import SwiftUI
import PlaygroundSupport
PlaygroundPage.current.setLiveView(
Text(Date(), style: Text.DateStyle.date)
)
Nota come nell'esempio ho omesso
.init
. Il motivo? Semplice abitudine e spesso e volentieri in grandi progetti l'init
non è esplicitato.
Ed eccoci che capiamo come Date
descrive date in un calendario e grazie al Text
potremo visualizzarle su schermo:
Recap
Type
è il blueprint che descrive in maniera astratta come si costruisce ed interagisce con un oggetto, mentre un oggetto è la rappresentazione reale di quel type.-
Una libreria o SDK o framework è una collezione di
Type
che ti facilitano nella creazione di app o features. Per esempioSwiftUI
è il framework che contiene tutti i type per creare User Interface. Il frameworkFoundation
offre i type di partenza per tutti i progetti Swift.import NomeFramework
importa tutte le definizione dei type all'interno di un file.
Gli oggetti si costruiscono utilizzando un
init
o una serie di parentesi tonde o graffe.Swift è un linguaggio type safe: operazioni ed interazioni tra oggetti sono controllate a compile time (mentre scrivi il codice).
Conclusione
Lo so che la teoria annoia, ma ti assicuro che i concetti affrontati in questa lezione rappresentano la base non solo di Swift e SwiftUI ma di moltissimi altri linguaggio di programmazione ad oggetti come Kotlin, Typescript e C#.
Capire la differenza tra Type
ed oggetti è il primo passo per essere considerati junior developer.
Ovviamente, non basterà solo questo ma almeno è un buon inizio.
Un altro importante step, soprattutto quando si è alle prime armi, è quello di imparare ad utilizzare e leggere la documentazione ufficiale. La documentazione ti aiuterà tantissimo nel comprendere nuovi Type
e come utilizzarli.
Buona programmazione!