Fino ad ora, abbiamo coperto le basi del linguaggio di programmazione Swift. Se hai seguito, dovresti ora avere una solida conoscenza di variabili, costanti, funzioni e chiusure. È giunto il momento di utilizzare ciò che abbiamo appreso e applicare tale conoscenza alle strutture orientate agli oggetti di Swift.
Per comprendere i concetti discussi in questo tutorial, è importante avere una conoscenza di base della programmazione orientata agli oggetti. Se non hai familiarità con classi, oggetti e metodi, ti consiglio di leggere prima questi argomenti prima di continuare con questo tutorial.
eBook: programmazione orientata agli oggetti con Swift
In questa lezione, esploreremo gli elementi costitutivi fondamentali della programmazione orientata agli oggetti in Swift, classi e strutture. In Swift, le classi e le strutture si sentono e si comportano in modo molto simile, ma ci sono alcune differenze chiave che è necessario comprendere per evitare le insidie più comuni.
In Objective-C, le classi e le strutture sono molto diverse. Questo non è vero per Swift. In Swift, ad esempio, sia le classi che le strutture possono avere proprietà e metodi. A differenza delle strutture C, le strutture in Swift possono essere estese e possono anche essere conformi ai protocolli.
La domanda ovvia è: "Qual è la differenza tra classi e strutture?" Torneremo su questa domanda più avanti in questo tutorial. Prima esploriamo come appare una classe in Swift.
Prima di iniziare a lavorare con classi e strutture, vorrei chiarire alcuni termini comunemente usati nella programmazione orientata agli oggetti. I termini classi, oggetti, e casi spesso confondono le persone nuove nella programmazione orientata agli oggetti. Pertanto, è importante sapere come Swift utilizza questi termini.
UN classe è un modello o modello per un'istanza di quella classe. Il termine "oggetto" è spesso usato per riferirsi a un'istanza di una classe. In Swift, tuttavia, le classi e le strutture sono molto simili e quindi è più facile e meno confuso usare il termine "istanza" per entrambe le classi e le strutture.
In precedenza in questa serie, abbiamo lavorato con le funzioni. Nel contesto di classi e strutture, di solito ci riferiamo a funzioni come metodi. In altre parole, i metodi sono funzioni che appartengono a una particolare classe o struttura. Nel contesto di classi e strutture, è possibile utilizzare entrambi i termini in modo intercambiabile poiché ogni metodo è una funzione.
Facciamo bagnare i piedi e definiamo una lezione. Accendi Xcode e crea un nuovo parco giochi. Rimuovere il contenuto del parco giochi e aggiungere la seguente definizione di classe.
classe Person
Il classe
parola chiave indica che stiamo definendo una classe chiamata Persona. L'implementazione della classe è racchiusa in un paio di parentesi graffe. Anche se il Persona
la classe non è molto utile nella sua forma attuale, è una classe Swift corretta e funzionale.
Come nella maggior parte degli altri linguaggi di programmazione orientati agli oggetti, una classe può avere proprietà e metodi. Nell'esempio aggiornato di seguito, definiamo tre proprietà:
nome di battesimo
, una proprietà variabile di tipo Stringa?
cognome
, una proprietà variabile di tipo Stringa?
luogo di nascita
: una proprietà costante di tipo Stringa
class Person var firstName: String? var lastName: String? let birthPlace = "Belgium"
Come illustra l'esempio, la definizione delle proprietà in una definizione di classe è simile alla definizione di variabili e costanti regolari. Noi usiamo il var
parola chiave per definire una proprietà variabile e il permettere
parola chiave per definire una proprietà costante.
Le proprietà di cui sopra sono anche conosciute come proprietà memorizzate. Più avanti in questa serie, impariamo a conoscere proprietà calcolate. Come suggerisce il nome, le proprietà memorizzate sono proprietà che vengono archiviate dall'istanza della classe. Sono simili alle proprietà in Objective-C.
È importante notare che ogni proprietà memorizzata deve avere un valore dopo l'inizializzazione o essere definita come un tipo facoltativo. Nell'esempio sopra, diamo il luogo di nascita
proprietà un valore iniziale di "Belgio"
. Questo dice a Swift che la proprietà del luogo di nascita è di tipo Stringa
. Più avanti in questo articolo, daremo un'occhiata all'inizializzazione in modo più dettagliato ed esploreremo come si lega all'inizializzazione delle proprietà.
Anche se abbiamo definito il luogo di nascita
proprietà come costante, è possibile cambiarne il valore durante l'inizializzazione di a Persona
esempio. Una volta che l'istanza è stata inizializzata, il luogo di nascita
la proprietà non può più essere modificata poiché abbiamo definito la proprietà come una proprietà costante con permettere
parola chiave.
Possiamo aggiungere un comportamento o una funzionalità a una classe attraverso funzioni o metodi. In molti linguaggi di programmazione, metodo è usato al posto di funzione nel contesto di classi e istanze. La definizione di un metodo è quasi identica alla definizione di una funzione. Nel prossimo esempio, definiamo il nome e cognome()
metodo nel Persona
classe.
class Person var firstName: String? var lastName: String? let birthPlace = "Belgium" func fullName () -> String var parts: [String] = [] se let firstName = self.firstName parts + = [firstName] se let lastName = self.lastName parts + = [ lastName] return parts.joined (separator: "")
Il metodo nome e cognome()
è annidato nella definizione della classe. Non accetta parametri e restituisce a Stringa
. L'implementazione del nome e cognome()
il metodo è semplice. Attraverso l'associazione opzionale, che abbiamo discusso in precedenza in questa serie, accediamo ai valori memorizzati nel nome di battesimo
e cognome
proprietà.
Memorizziamo il nome e il cognome del Persona
istanza in un array e unire le parti con uno spazio. La ragione di questa implementazione un po 'imbarazzante dovrebbe essere ovvia: il nome e il cognome possono essere vuoti, motivo per cui entrambe le proprietà sono di tipo Stringa?
.
Abbiamo definito una classe con alcune proprietà e un metodo. Come creiamo un'istanza di Persona
classe? Se hai familiarità con Objective-C, allora amerai la concisione del seguente frammento.
let john = Person ()
Istanziare un'istanza di una classe è molto simile al richiamo di una funzione. Per creare un'istanza, il nome della classe è seguito da una coppia di parentesi e il valore di ritorno è assegnato a una costante o variabile.
Nel nostro esempio, la costante John
ora punta a un'istanza di Persona
classe. Questo significa che non possiamo cambiare nessuna delle sue proprietà? Il prossimo esempio risponde a questa domanda.
john.firstName = "John" john.lastName = "Doe" john.birthPlace = "Francia"
Possiamo accedere alle proprietà di un'istanza utilizzando la comodità della sintassi del punto. Nell'esempio, abbiamo impostato nome di battesimo
a "John"
, cognome
a "Doe"
, e luogo di nascita
a "Francia"
. Prima di trarre conclusioni basate sull'esempio precedente, dobbiamo verificare eventuali errori nel campo da gioco.
Ambientazione nome di battesimo
e cognome
non sembra causare problemi. Ma assegnando "Francia"
al luogo di nascita
la proprietà genera un errore. La spiegazione è semplice.
Nonostante John
è dichiarato come una costante, che non ci impedisce di modificare il Persona
esempio. C'è un avvertimento, però: solo le proprietà variabili possono essere modificate dopo l'inizializzazione di un'istanza. Le proprietà definite come costanti non possono essere modificate una volta assegnato un valore.
Una proprietà costante può essere modificata durante l'inizializzazione di un'istanza. Mentre il luogo di nascita
la proprietà non può essere cambiata una volta a Persona
l'istanza è creata, la classe non sarebbe molto utile se potessimo solo istanziare Persona
istanze con un luogo di nascita di "Belgio". Facciamo il Persona
classe un po 'più flessibile.
L'inizializzazione è una fase della durata di un'istanza di una classe o di una struttura. Durante l'inizializzazione, prepariamo l'istanza per l'utilizzo popolando le sue proprietà con i valori iniziali. L'inizializzazione di un'istanza può essere personalizzata implementando un inizializzatore, un tipo speciale di metodo. Definiamo un inizializzatore per il Persona
classe.
class Person var firstName: String? var lastName: String? let birthPlace = "Belgium" init () birthPlace = "France" ...
Abbiamo definito un inizializzatore, ma ci imbattiamo in diversi problemi. Dai un'occhiata all'errore che il compilatore ci ha lanciato.
Non solo l'inizializzatore è inutile, il compilatore ci avverte anche che non possiamo modificare il valore di luogo di nascita
proprietà poiché ha già un valore iniziale. Possiamo risolvere l'errore rimuovendo il valore iniziale del file luogo di nascita
proprietà.
class Person var firstName: String? var lastName: String? let birthPlace: String init () birthPlace = "France" ...
Si noti che il nome dell'inizializzatore, dentro()
, non è preceduto dal func
parola chiave. A differenza degli inizializzatori in Objective-C, un inizializzatore in Swift non restituisce l'istanza in fase di inizializzazione.
Un altro dettaglio importante è come impostiamo il luogo di nascita
proprietà con un valore iniziale. Abbiamo impostato il luogo di nascita
proprietà usando il nome della proprietà, ma va anche bene essere più espliciti in questo modo.
init () self.birthPlace = "France"
Il se stesso
parola chiave si riferisce all'istanza che viene inizializzata. Ciò significa che self.birthPlace
si riferisce a luogo di nascita
proprietà dell'istanza. Possiamo omettere se stesso
, come nel primo esempio, perché non c'è confusione su quale proprietà ci riferiamo. Questo non è sempre il caso, però. Lascia che ti spieghi cosa intendo.
L'inizializzatore che abbiamo definito non è molto utile al momento, e non risolve il problema da cui siamo partiti: essere in grado di definire il birthplace di una persona durante l'inizializzazione.
In molte situazioni, si desidera passare i valori iniziali all'inizializzatore per personalizzare l'istanza che si sta creando. Questo è possibile creando un inizializzatore personalizzato che accetta uno o più argomenti. Nell'esempio seguente, creiamo un inizializzatore personalizzato che accetta un argomento, luogo di nascita
, di tipo Stringa
.
init (birthPlace: String) self.birthPlace = birthPlace
Vale la pena sottolineare due cose. In primo luogo, ci viene richiesto di accedere a luogo di nascita
proprietà attraverso self.birthPlace
per evitare ambiguità poiché il nome del parametro locale è uguale a luogo di nascita
. In secondo luogo, anche se non abbiamo specificato un nome di parametro esterno, Swift per impostazione predefinita crea un nome di parametro esterno uguale al nome del parametro locale.
Nell'esempio seguente, istanziamo un altro Persona
istanza invocando l'inizializzatore personalizzato appena definito.
let maxime = Person (birthPlace: "France") print (maxime.birthPlace)
Passando un valore per il luogo di nascita
parametro per l'inizializzatore, possiamo assegnare un valore personalizzato alla costante luogo di nascita
proprietà durante l'inizializzazione.
Come in Objective-C, una classe o una struttura possono avere più inizializzatori. Nell'esempio seguente, ne creiamo due Persona
le istanze. Nella prima riga, usiamo l'inizializzatore di default. Nella seconda riga, utilizziamo l'inizializzatore personalizzato che abbiamo definito in precedenza.
let p1 = Person () let p2 = Person (birthPlace: "France")
Le strutture sono sorprendentemente simili alle classi, ma ci sono alcune differenze chiave. Iniziamo definendo una struttura di base.
struct Wallet var dollars: Int var cents: Int
A prima vista, l'unica differenza è l'uso del struct
parola chiave anziché il classe
parola chiave. L'esempio mostra anche un approccio alternativo per fornire i valori iniziali alle proprietà. Invece di impostare un valore iniziale per ogni proprietà, possiamo dare alle proprietà un valore iniziale nell'inizializzatore della struttura. Swift non genera un errore, poiché ispeziona anche l'inizializzatore per determinare il valore iniziale e il tipo di ogni proprietà.
Potresti iniziare a chiedermi quale sia la differenza tra classi e strutture. A prima vista, sembrano identici nella forma e nella funzione, ad eccezione del classe
e struct
parole chiave. Esistono tuttavia alcune differenze chiave.
Le classi supportano l'ereditarietà, mentre le strutture no. Il seguente esempio illustra questo. Il modello di progettazione dell'eredità è indispensabile nella programmazione orientata agli oggetti e, in Swift, è una differenza fondamentale tra classi e strutture.
class Person var firstName: String? var lastName: String? Let birthPlace: String init (birthPlace: String) self.birthPlace = birthPlace Studente: Person var school: String? let student = Student (birthPlace: "France")
Nell'esempio sopra, il Persona
la classe è il genitore o la superclasse del Alunno
classe. Ciò significa che il Alunno
la classe eredita le proprietà e il comportamento del Persona
classe. L'ultima riga illustra questo. Inizializziamo a Alunno
istanza richiamando l'inizializzatore personalizzato definito in Persona
classe.
Il seguente concetto è probabilmente il concetto più importante in Swift che imparerai oggi, la differenza tra tipi di valore e tipi di riferimento. Le strutture sono tipi di valore, il che significa che vengono passati per valore. Un esempio illustra meglio questo concetto.
struct Point var x: Int var y: Int init (x: Int, y: Int) self.x = x self.y = y var point1 = Punto (x: 0, y: 0) var point2 = point1 point1.x = 10 print (point1.x) // 10 print (point2.x) // 0
Definiamo una struttura, Punto
, incapsulare i dati per memorizzare una coordinata in uno spazio bidimensionale. Noi istanziare point1
con X
uguale a 0
e y
uguale a 0
. Noi assegniamo point1
a point2
e impostare il X
coordinata di point1
a 10
. Se produciamo il X
coordinate di entrambi i punti, scopriamo che non sono uguali.
Le strutture vengono passate per valore, mentre le classi vengono passate per riferimento. Se si intende continuare a lavorare con Swift, è necessario comprendere la dichiarazione precedente. Quando abbiamo assegnato point1
a point2
, Swift ha creato una copia di point1
e lo ha assegnato a point2
. In altre parole, point1
e point2
ogni punto a una diversa istanza del Punto
struttura.
Ripetiamo ora questo esercizio con il Persona
classe. Nell'esempio seguente, istanziamo a Persona
esempio, imposta le sue proprietà, assegna persona1
a Person2
, e aggiorna il nome di battesimo
proprietà di persona1
. Per vedere che cosa passa per riferimento significa per le classi, produciamo il valore di nome di battesimo
proprietà di entrambi Persona
casi.
var person1 = Persona (birthPlace: "Belgium") person1.firstName = "Jane" person1.lastName = "Doe" var person2 = person1 person1.firstName = Stampa "Janine" (person1.firstName!) // Stampa di Janine (persona2. firstName!) // Janine
L'esempio dimostra che le classi sono tipi di riferimento. Ciò significa che persona1
e Person2
fare riferimento o riferimento allo stesso Persona
esempio. Assegnando persona1
a Person2
, Swift non crea una copia di persona1
. Il Person2
variabile punti allo stesso Persona
esempio persona1
sta puntando Cambiare il nome di battesimo
proprietà di persona1
colpisce anche il nome di battesimo
proprietà di Person2
, perché si riferiscono allo stesso modo Persona
esempio.
Come ho già detto più volte in questo articolo, le classi e le strutture sono molto simili. Ciò che separa classi e strutture è molto importante. Se i concetti di cui sopra non sono chiari, allora ti incoraggio a leggere l'articolo ancora una volta per far affondare i concetti che abbiamo coperto.
In questa puntata di Swift From Scratch, abbiamo iniziato ad esplorare le basi della programmazione orientata agli oggetti in Swift. Classi e strutture sono gli elementi costitutivi fondamentali della maggior parte dei progetti Swift e ne apprenderemo di più nelle prossime lezioni di questa serie.
Nella prossima lezione, continueremo la nostra esplorazione di classi e strutture dando un'occhiata più da vicino alle proprietà e all'eredità.
Se vuoi imparare come usare Swift 3 per codificare le applicazioni del mondo reale, consulta il nostro corso Crea app per iOS con Swift 3. Che tu sia nuovo nello sviluppo di app per iOS o che stia cercando di passare da Objective-C, questo corso ti consentirà di iniziare con Swift per lo sviluppo di app.