Scopri Objective-C Day 2

Benvenuti alla seconda parte di questa serie introduttiva su Objective-C. Dopo aver passato la scorsa settimana a rivedere i fondamenti del linguaggio C su cui è stato costruito l'Objective-C, questa settimana passeremo a concentrarci su ciò che rende Objective-C un linguaggio così eccezionale per lo sviluppo del software. Nello specifico, discuteremo i fondamenti dell'Object Oriented Programming (OOP) e mostreremo come creare una classe e inviare messaggi agli oggetti in Objective-C.

Programmazione orientata agli oggetti

Perché abbiamo Objective-C? Perché non usare semplicemente il linguaggio C sottostante? Il motivo per cui abbiamo Objective-C è quello di darci un campo di giochi orientato agli oggetti all'interno del quale costruire le nostre applicazioni. OOP è un paradigma di programmazione che tenta di consentire agli sviluppatori di pensare alla progettazione del software in termini di oggetti e attributi anziché variabili e funzioni. Nello specifico, OOP tenta di ottenere l'astrazione, l'incapsulamento, la modularità, il polimorfismo e l'ereditarietà dei dati. L'argomento di OOP potrebbe facilmente riempire un libro (o una serie di tutorial) da solo, quindi invece ti introdurrò ai principi di base a titolo di esempio.

Immagina di avere una macchina. Puoi pensare alla tua macchina come a un oggetto. Ci sono molte altre macchine nel mondo e potresti persino possederne più di una. La tua auto ha diverse proprietà: marca, modello, colore, tipo di motore e molto altro. Nei termini di programmazione orientata agli oggetti, chiameremmo il concetto astratto di un'auto una "classe" e l'auto individuale che possiedi un oggetto o istanza (oggetto istanziato) della classe. Quando viene prodotta una nuova auto, viene creata un'istanza (o creata) di una nuova istanza della classe di auto e viene fornita una serie di proprietà.

Ancora un po 'sfocato? Un'altra grande analogia è quella del cookie e del cookie cutter. La classe è il cookie cutter e l'oggetto è il cookie.

Quindi, perché pensare in termini di oggetti? Una delle migliori ragioni è perché questo è il modo in cui il tuo cervello concettualizza la vita nel mondo reale, e ci sono molti vantaggi nell'essere in grado di astrarre lo sviluppo del software in termini simili.

Le classi (e quindi gli oggetti) sono costituite da metodi e attributi. Se provieni da un altro linguaggio di programmazione, potresti essere più familiare equiparando i metodi con le funzioni e gli attributi con le variabili. Ne discuteremo a turno dopo.

metodi

Quindi abbiamo una "istanza" di un'auto, ora che cosa ne facciamo? Bene, lo guidiamo e lo riempiamo di benzina, tra le altre cose. Guidare e riempire di benzina si applicano solo alle auto che usiamo, il che significa che quando riempiamo una macchina o guidiamo una macchina, stiamo influenzando solo un'istanza, e non tutte le auto del mondo. Pertanto, il riempimento dell'istanza dell'automobile è considerato un metodo di istanza. È qualcosa che facciamo alla nostra istanza e solo alla nostra istanza.

D'altra parte, se chiediamo alla classe dell'auto originale quanti colori di auto sono disponibili, questo è un metodo di classe perché non stiamo parlando solo della macchina che guidiamo, ma di tutte le auto in generale.

Molti di questi principi diventano più chiari con l'uso, quindi diamo un'occhiata ad un po 'di sintassi.

In Objective-C, chiamiamo metodi object passando messaggi. Quando vogliamo sapere quanto gas è nella nostra istanza di auto, quindi inviamo un messaggio alla nostra istanza e il messaggio è il metodo che vogliamo applicare. A livello di codice appare così:

 [messaggio destinatario]; 

Le parentesi indicano che stiamo inviando un messaggio. Il primo parametro è chi dovrebbe ricevere questo messaggio e il secondo parametro è ciò che effettivamente è il messaggio. Infine, terminiamo con un punto e virgola comune alla maggior parte dei linguaggi di programmazione.

Quindi, con il nostro esempio precedente in mente, questo è il modo in cui interagiremmo con la nostra istanza di auto per aggiungere gas al serbatoio;

 [dansCar addGas]; 

L'esempio precedente presuppone che abbiamo istanziato un'istanza della classe Car e l'abbiamo chiamata "dansCar". Quindi passiamo il messaggio "addGas" all'oggetto "dansCar", che equivale a chiamare una funzione. In un'altra lingua, questa riga potrebbe essere simile a:

 dansCar.addGas (); 

attributi

Diciamo che la nostra classe di auto ha un serbatoio di gas che viene memorizzato in percentuale. Ad esempio, se il serbatoio del gas è al 50%, significa che è pieno a metà e se è al 100% significa che è pieno fino all'orlo. Ora, se vogliamo sapere quanta benzina c'è nel serbatoio, non prendiamo direttamente le informazioni da un attributo. Invece, useremmo un metodo accessor per accedere alla variabile interna per noi. Allo stesso modo, quando vogliamo riempire il serbatoio, non diamo solo una nuova percentuale all'attributo del serbatoio del gas, ma usiamo un setter per aggiornare l'attributo per noi. Questo processo è noto come incapsulamento dei dati.

Ciò che intendiamo per incapsulazione dei dati è che i dati sono contenuti (per così dire) con metodi che intendono accedervi, dobbiamo usare metodi. Alcuni di voi che hanno programmato in altre lingue e non hanno sentito parlare di incapsulamento dei dati potrebbero chiedersi perché facciamo le cose in questo modo. La risposta è che incapsulando i dati, c'è un bel cuscino tra lo sviluppatore di una classe e l'utente di una classe. Poiché i metodi di classe gestiscono e mantengono gli attributi all'interno della classe, possono conservare più facilmente l'integrità dei dati. Un altro importante vantaggio è che quando uno sviluppatore distribuisce la sua classe, le persone che la utilizzano non devono preoccuparsi affatto degli interni della classe. Uno sviluppatore può aggiornare un metodo per renderlo più veloce o più efficiente, ma questo aggiornamento è trasparente per l'utente della classe poiché usa ancora lo stesso metodo senza modificare il suo codice.

Questo ci porta bene alla prossima sezione che andremo a vedere, che è come Objective-C separa l'interfaccia dall'implementazione.

Interfaccia e implementazione

Quando crei o lavori con una semplice classe in Objective-C vedrai che, di default, ha due file. Uno è il file di implementazione che è un file che termina con un suffisso di .m e il file di interfaccia che è un file che termina con un suffisso di .h.

Interfaccia

 #importare  @interface Car: NSObject // Questo è dove gli attributi diventano float fillLevel;  // Ecco dove vanno i metodi - (void) addGas; @fine 

Prima di tutto, stiamo importando Cocoa.h che è una libreria standard con un sacco di codice riutilizzabile che possiamo usare all'interno della nostra app.

Quindi, dichiariamo che questa è l'interfaccia per la macchina, ma inseriamo anche NSObject in quella dichiarazione. Aggiungendo ": NSObject" significa che la classe Car eredita dalla classe NSObject. Parleremo di più sull'ereditarietà in un futuro tutorial.

La nostra variabile di istanza "fillLevel" viene dichiarata successivamente, e specifichiamo che è del tipo di dati "float" in modo da poter rappresentare facilmente una percentuale.

La riga successiva dichiara il nostro metodo "addGas". Il "-" indica che questo è un metodo di istanza, non un metodo di classe. La parte "(void)" significa che il metodo non restituirà nulla quando termina l'esecuzione. Se la classe restituisse un numero intero, questo verrà modificato in "(int)" e lo stesso per qualsiasi altro tipo di dati. Infine, finalizziamo la dichiarazione del metodo con un punto e virgola.

Implementazione

 #import "Car.h" @implementation Car - (void) addGas // codice va qui per aggiungere gas @end 

L'implementazione in questo caso contiene il metodo per aggiungere gas al serbatoio. Importiamo anche Car.h, che è il file dell'interfaccia. Dove risiede il nostro metodo addGas, potremmo aggiungere molti altri metodi, ma lo scopo di oggi è semplicemente farti capire come funzionano le classi piuttosto che fare una classe a tutti gli effetti.

La prossima volta

La prossima volta vedremo più in profondità i metodi e l'uso delle variabili con i metodi (oltre alle basi della gestione delle variabili in Objective-C). Questo tutorial non è stato troppo lungo poiché spesso confonde i nuovi sviluppatori sul perché separiamo le classi in più di un file. Se ti senti per niente confuso, ti preghiamo di rileggere quanto sopra o di porre domande nella sezione commenti qui sotto. Le lezioni saranno una costante ripetizione in questa serie ed è importante che tu capisca come funzionano.

Sfida

Visto che questa parte della serie era abbastanza teorica, non c'è molto che puoi fare per esercitarti. Tuttavia, mi raccomando questa settimana che ti iscrivi al sito web degli sviluppatori di Apple in quanto è un riferimento inestimabile. Una volta che hai fatto questo, fai un po 'di curiosità su alcuni dei loro corsi scaricabili e scarica alcuni di quelli semplici. Non è necessario comprendere tutto il codice, basta osservare come le classi sono formate e separate tra i file.