În cadrul acestui episod vom introduce noțiunile de variabilă și tip de date și vom lucra cu numere și texte. Vom presupune că deja știți să creați un playground în xCode; dacă nu, vă recomandăm să citiți din nou episodul anterior.
Variabile
Chiar și pentru cele mai simple programe, la un moment dat avem nevoie să păstrăm anumite informații. Nu am avut nevoie de acest lucru atunci când doar am afișat un mesaj, dar atunci când am avut nevoie de numele utilizatorului a trebuit să păstrăm informația respectivă.
Să ne imaginăm următorul scenariu: cineva ne spune numele și dorim să îl salutăm. Salutul va fi format din cuvântul Salut, urmat de un spațiu, numele persoanei și un semn de exclamare. Codul Swift ar putea arăta astfel:
1 2 |
var nume = "GInfo" println("Hello " + nume + "!") |
În prima linie, avem o instrucțiune prin care păstrăm numele persoanei în ceva de numit nume. Aceasta este o așa numită variabilă.
Variabilele pot fi văzute ca fiind niște recipiente care păstrează informații. Practic, cu ajutorul lor ajungem undeva în memoria calculatorului, luăm o mică parte din ea și îi dăm o denumire pentru a o putea folosi ulterior.
Avem nevoie de variabile pentru cele mai diverse scopuri. Dacă scriem un program care controlează un roboțel, vom avea nevoie de variabile care să conțină poziția acestuia, orientarea sa etc. În schimb, dacă programul nostru simulează un joc de fotbal, am avea nevoie de variabile pentru a păstra scorul.
În principiu, dacă trebuie să ținem minte ceva, cel mai simplu este să punem acel ceva într-o variabilă.
Majoritatea limbajelor moderne necesită declararea unei variabile înainte ca aceasta să poată fi utilizată. Swift este un astfel de limbaj.
Dacă revenim la prima linie a programului nostru, observăm că înaintea denumirii nume, apare cuvântul var. Acesta indică faptul că dorim să declarăm o variabilă.
În Swift, pentru a declara o variabilă, trebuie să folosim cuvântul var, apoi să precizăm denumirea sa, urmată de două puncte și de tipul acesteia. Pentru un meci de fotbal, am putea avea o variabilă declarată astfel:
1 |
var goluriGazde:Int |
Tipul este Int (vom vedea ce înseamnă), iar denumirea este goluriGazde (vom vedea și de ce denumirea arată oarecum ciudat); declararea unei variabile este o instrucțiune.
Termenul variabilă implică faptul că ea se poate modifica. Prin diverse mecanisme, informația conținută de o variabilă se poate schimba în timpul execuției programului. De exemplu, într-un joc de fotbal, la începutul unui meci variabila care ar păstra numărul golurilor marcate de echipa gazdă ar conține informația 0. Dar, dacă echipa marchează un gol, informația respectivă trebuie să devină 1. Dacă se mai marchează unul, variabila va conține informația 2 și așa mai departe. Dar, dacă începe un joc nou, informația redevine 0. Această informație păstrată de către variabilă poartă denumirea de valoare a variabilei.
În Swift, este posibil ca în momentul declarării unei variabile să precizăm și ce valoare dorim să aibă la început. Pentru aceasta, după tipul ei adăugăm semnul =, urmat de valoarea dorită. O astfel de declarație ar putea fi:
1 |
var goluriGazde:Int = 0 |
Spunem că o astfel de variabilă este inițializată.
Dacă inițializăm variabila, tipul acesteia poate fi determinăm pe baza valorii folosite pentru inițializare. Ni se permite să îl omitem.Spunem că tipul este implicit. Dacă decidem să specificăm tipul, acesta este explicit. Totuși, trebuie să indicăm faptul că dorim să declarăm o variabilă. Următoarea declarație este echivalentă cu cea anterioră:
1 |
var goluriGazde = 0 |
Tipuri
Am spus că în Swift variabilele au tipuri. Tipul unei variabile indică ce fel de informație poate conține variabila respectivă. În exemplul nostru tipul este Int; el arată că variabila noastră este un număr întreg. Dacă o variabilă are un anumit tip, atunci informația conținută trebuie să fie compatibilă cu acel tip. Putem scrie:
1 |
var goluriGazde:Int = 2457 |
Chiar dacă este puțin probabil să găsim vreun sport în care o echipă să marcheze 2457 de goluri, instrucțiunea este corectă fiindcă, din punctul de vedere al calculatorului, goluriGazde este un număr întreg și valoarea sa poate fi orice număr întreg acceptabil (vom vedea mai încolo că există anumite restricții).
Totuși, nu putem scrie:
1 |
var goluriGazde:Int = "GInfo" |
GInfo este în acest caz un text (vom vedea puțin mai târziu rolul ghilimelelor) și variabila goluriGazde nu poate conține decât numere întregi. Dar, este perfect corect să scriem:
1 |
var goluriGazde = "GInfo" |
În acest caz tipul implicit este String. Pare ciudat și nu este deloc intuitiv. Ne-am așteptat ca ceva numit goluriGazde să fie un număr. Totuși, limbajul ne permite acest lucru. Trebuie să ne amintim că un calculator face ce îi spunem să facă, nu ce am vrea noi să facă.
Variabilele pot avea diverse tipuri: ele pot fi numere întregi, numere cu zecimale (acestea sunt denumite uneori numere reale, dar nu e chiar corect), texte etc. Dar putem avea și tipuri mult mai complexe; putem avea variabile care reprezintă clădiri, animale, galaxii, atomi și așa mai departe.
Unele tipuri sunt disponibile direct, altele trebuie inventate. Cele disponibile pot fi utilizate imediat; cele create deja de alții pot fi și ele utilizate. Dar, tipurile noi trebuie întâi definite.
Iată câteva exemple de declarații (împreună cu inițializările):
1 2 3 4 5 |
var a:Int = 5 var b:Double = 5.1 var c:Character = '+' var d:Bool = true var s:String = "GInfo" |
Avem așadar un număr întreg a care are deocamdată valoarea 5, un număr cu zecimale b care are valoarea 5.1, un caracter c care are valoarea + și un așa numit boolean d cu valoarea true (adevărat), valorile booleene trebuie scrise în engleză și pot fi true sau false. În sfârșit, avem un șir de caractere s care conține textul GInfo.
Despre tipurile mai complicate vom discuta cu altă ocazie.
Numere
În Swift există mai multe feluri de numere și chiar mai multe feluri de numere întregi. Știm că avem o infinitate de numere întregi. Pentru numere foarte mari, noi am nevoie să scriem multe cifre; la fel, calculatoarele ar avea nevoie să folosească tot mai multă memorie pe măsură ce numerele sunt mai mari. Dar, memoria calculatoarelor este finită. Diferitele variante de numere întregi ne spun cam câtă memorie dorim să utilizăm. Din acest motiv, pentru fiecare tip vom putea avea valori care nu depășesc o valoare maximă, specifică tipului. Semnul unui număr întreg e și el în memorie, deci putem avea și numere negative. Dar, datorită memoriei limitate, numerele trebuie să fie mai mari decât o valoare minimă specifică tipului. Anumite tipuri permit doar utilizarea numerelor pozitive.
Pare complicat și ciudat, dar nu e chiar așa. În practică nu utilizăm numere foarte mari. În cele mai multe situații este suficient tipul Int32 (valoarea maximă este 231 - 1, adică două miliarde și ceva). Uneori nu este suficient și avem nevoie de Int64. Valoarea maximă este 263 - 1, adică aproape zece miliarde de miliarde. Dacă avem nevoie de valori și mai mari e mai complicat, dar sunt soluții. Există și tipul Int, care este echivalent cu Int32 pe platformele cu 32 de biți sau Int64 pe cele cu 64 de biți.
Am văzut cum declarăm o variabilă și cum o inițializăm. Dar, am spus că valorile variabilelor se pot modifica. Pentru aceasta avem nevoie de o instrucțiune. O astfel de instrucțiune arată așa:
1 |
a = 2457 |
Valoarea variabilei a va fi acum 2457 indiferent care a fost înainte. Informația înlocuită se pierde. Nu vom ști cât a fost acea valoare înainte, deci dacă avem nevoie de ea, ar fi fost bine să o punem altundeva (într-o altă variabilă de exemplu).
Instrucțiunea anterioară este validă numai dacă a este într-adevăr o variabilă de tip numeric. Ea trebuie să fi fost declarată anterior (nu neapărat și inițializată).
Să nu credeți că a = 2457 este o ecuație sau ceva asemănător; este o comandă. Calculatorului i se spune ca în zona de memorie corespunzătoare variabilei a să fie pusă valoarea 2457. O astfel de comandă se numește atribuire.
Printr-o instrucțiune de atribuire, unei variabile i se dă o valoare. Tipul acestei valori trebuie să fie compatibil cu cel al variabilei (vom vedea ulterior de ce, în unele cazuri, e posibil ca tipurile să nu fie chiar identice).
Așadar, o instrucțiune de atribuire conține denumirea variabilei care va primi valoarea, urmată se semnul = și apoi de valoarea propriu zisă. În cazul nostru, valoarea a fost numărul 2457.
Există mai multe modalități de a reprezenta numerele; 2457 este varianta care ni se pare nouă naturală; nu e nicio șmecherie, e chiar numărul care urmează după 2456 și e înainte de 2458. Fără să explicăm de ce și doar pentru a arăta că se poate și altfel dacă chiar vrem, același număr poate fi reprezentat prin 0x999. Instrucțiunea următoare are exact același efect:
1 |
a = 0x999; |
În Swift, numerele sunt numere simple dacă nu apare nimic altceva lipit de ele. Alte simboluri sau caractere le modifică semnificația. Partea 999 din 0x999 nu reprezintă deloc numărul 999.
Lucrurile pot deveni și mai ciudate: 2 și "2" sunt complet diferite. Primul este numărul 2, al doilea este un caracter care reprezintă cifra 2 sau un string. Mai multe despre caractere și string-uri în secțiunea următoare.
Numerele cu zecimale pot și ele fi reprezentate așa cum ni se pare nouă natural; 2.5 este o valoare corectă; dar, putem avea și ciudățenii ca 1e-4.
Nu dorim să explicăm aceste lucruri care par bizare; dorim doar să atragem atenția că în multe cazuri lucrurile nu sunt ceea ce par.
Caractere și string-uri
În Swift un caracter reprezintă un simbol. Poate fi o literă, o cifră, un semn de punctuație, un operator matematic etc. Valoarea unui caracter este cuprinsă între ghilimele. În principiu, ghilimele, un semn și apoi din nou ghilimele. De exemplu, caracterul + trebuie scris "+".
Dar, ce ne facem dacă vrem să avem chiar valoarea ghilimele? Ați putea crede că """ este soluția, dar nu e chiar așa. Cea de-a doua apariție a ghilimelelor este interpretată ca fiind sfârșitul elementelor care descriu caracterul și a treia nu mai este înțeleasă. Ca urmare, instrucțiunea c = """ nu este corectă.
Ni se oferă o soluție… Putem marca a doua apariție cu un simbol special care să indice faptul că acesta nu trebuie interpretat ca sfârșit al descrierii caracterului, ci ca semn propriu-zis. Elementul special este \ (backslash). Varianta corectă a instrucțiunii este:
1 |
c = "\"" |
Ar părea că ni s-au rezolvat toate problemele, dar… dacă avem nevoie fix de backslash? c = "\" nu e corect fiindcă backslash-ul indică faptul că următorul element trebuie interpretat ca fiind semnul ghilimele. Soluți este să marcăm semnul backslash cu un alt backslash. Deci, pentru a atribui unei variabile valoarea \, va trebui să scriem:
1 |
c = "\\"; |
String-urile sunt și ele cuprinse între ghilimele. Ați ghicit probabil, dacă unul dintre caracterele string-ului este chiar ", avem o problemă. Probabil intuiți soluția, vom marca astfel de caractere cu backslash. Este în continuare prezentă cea cu backslash-ul (trebuie și aici dublat).
Dar… avem probleme suplimentare. Spuneam că string-urile sunt folosite în special pentru a păstra valori care reprezintă texte. Și textele pot avea mai multe linii. Cum facem?
Dacă scriem:
1 2 3 |
s = "Gazeta de Informatică" |
vom vedea că nu e corect.
Avem conceptul de caracter special de sfârșit de linie. Dacă dorim să avem textul Gazeta de Informatică scris pe trei rânduri (câte un cuvânt pe o linie), vom scrie:
1 |
s = "Gazeta\nde\nInformatică" |
Va urma
În cadrul episodului următor vom prezenta detalii referitoare la modul în care sunt efectuate operațiile (nu neapărat matematice) și vom vedea ce sunt și la ce sunt folosite comentariile.