de Saul Costa

Programare orientată pe obiecte (OOP) este o paradigmă de programare organizată în jurul obiectelor. La un nivel ridicat, OOP se referă la posibilitatea de a structura codul, astfel încât funcționalitatea acestuia să poată fi partajată în întreaga aplicație. Dacă este făcut corect, OOP poate duce la programe scrise foarte elegant, care au o duplicare minimă a codului.

Acest lucru se opune programării procedurale (PP), în care creați programe în ordine secvențială și metode de apelare atunci când doriți un comportament partajat între pagini din aplicație. Limbajele de programare procedurale comune includ C și Merge.

În acest tutorial, veți învăța conceptele fundamentale ale OOP pentru Rubin, un limbaj de programare orientat pe obiecte în care totul este un obiect. Vom folosi Ruby, deoarece unul dintre atributele sale definitorii – pe lângă sintaxa elegantă și lizibilitatea sa – este modul în care implementează tehnicile OOP. Acest lucru îl face un limbaj excelent pentru a începe să înveți OOP.

Vom acoperi:

  • Crearea de clase
  • Instanțarea obiectelor
  • Initializarea argumentelor
  • Lucrul cu moștenirea și
  • Metode private și publice.

În învățarea acestor concepte, vom construi propria noastră aplicație: un conector API care comunică dinamic cu o aplicație care trimite un mesaj text. Aceasta va include parcurgerea modului de valorificare a conceptelor precum moștenirea și instanțierea obiectelor pentru a face codul nostru mai scalabil și reutilizabil!

Acest scurt tutorial este adaptat de la Next Tech’s Introducere în cursul Ruby, care include un mediu de testare în browser și sarcini interactive verificate automat pentru finalizare.

Puteți urmări împreună cu fragmentele de cod din acest tutorial folosind sandbox-ul Next Tech, care are deja Ruby preinstalat. Dacă ați ales să utilizați propriul IDE, asigurați-vă că Ruby este instalat urmând instrucțiunile de pe pagina de instalare.

Crearea de clase

Înainte de a începe, să definim ce anume obiect este. În esență, un obiect este o bucată de cod autonomă care conține date („atribute”) și comportament („metode”) și poate comunica cu alte obiecte. Obiecte de același tip sunt create din clase, care acționează ca planuri care definesc proprietăți și comportament.

Crearea unei clase în Ruby este destul de ușoară. Pentru a defini o clasă, pur și simplu tastați class cuvânt urmat de numele clasei și încheiați-l cu end cuvânt. Orice conține între class și end aparține acestei clase.

Numele claselor din Ruby au o cerință de stil foarte specifică. Ei trebuie să înceapă cu o literă și, dacă reprezintă mai multe cuvinte, fiecare cuvânt nou trebuie să fie, de asemenea, o literă mare – adică „CamelCase”.

Vom începe prin a crea o clasă numită ApiConnector:

Cursurile din Ruby pot stoca atât date, cât și metode. În multe limbaje tradiționale OOP, cum ar fi Java, trebuie să creați două metode pentru fiecare element de date pe care doriți să îl includeți în clasă. O metodă, setter, setează valoarea din clasă. Cealaltă metodă, getter, vă permite să recuperați valoarea.

Procesul de creare a metodelor setter și getter pentru fiecare atribut de date poate fi obositor și duce la definiții de clasă incredibil de lungi. Din fericire, Ruby are un set de instrumente numit atribute accesorii.

Să implementăm câțiva setatori și getters pentru câteva elemente de date noi pentru clasa noastră. Deoarece este un conector API, ar avea sens să ai elemente de date precum title, description, și url. Putem adăuga aceste elemente cu următorul cod:

Când creați doar o clasă, aceasta nu face nimic – este pur și simplu o definiție. Pentru a lucra cu clasa, trebuie să creăm o instanță a acesteia … vom acoperi asta în continuare!

Instanțierea

Pentru a înțelege ce instanțierea este, să luăm în considerare o analogie din lumea reală. Să ne imaginăm că construiești o casă. Prima sarcină este de a construi un plan pentru casă. Acest plan ar conține atribute și caracteristici ale casei, cum ar fi dimensiunile fiecărei camere, modul în care va curge instalațiile sanitare și așa mai departe.

Planul casei este casa reală? Desigur că nu, pur și simplu enumeră atributele și elementele de design pentru modul în care va fi creată locuința. Deci, după ce planul este finalizat, locuința propriu-zisă poate fi construită – sau „instanțiată”.

Așa cum s-a explicat în secțiunea anterioară, în OOP, o clasă este planul unui obiect. Descrie pur și simplu cum va arăta un obiect și cum se va comporta. Prin urmare, instanțierea este procesul de a lua o definiție de clasă și de a crea un obiect pe care îl puteți utiliza într-un program.

Să creăm o nouă instanță a noastră ApiConnector clasa și stocați-l într-o variabilă numită api:

Acum că avem un obiect creat, putem folosi api variabilă pentru a lucra cu atributele clasei. De exemplu, putem rula codul:

[Out:]https://next.tech

În plus față de crearea atributelor, puteți crea și metode în cadrul unei clase:

Pentru a accesa această metodă, putem utiliza aceeași sintaxă pe care am folosit-o cu accesorii de atribute:

Punând toate acestea împreună, rularea codului complet al clasei de mai jos va avea ca rezultat url si test_method mesaj de imprimat:

[Out:]"https://next.tech""testing class call"

Metoda inițializatorului

Un lucru pe care îl puteți găsi la îndemână în dezvoltarea Ruby este abilitatea de a crea un inițializator metodă. Aceasta este pur și simplu o metodă numită initialize care va rula de fiecare dată când creați o instanță a clasei dvs. În această metodă, puteți da valori variabilelor dvs., puteți apela alte metode și puteți face aproape orice credeți că ar trebui să se întâmple atunci când se creează o nouă instanță a acelei clase.

Să ne actualizăm ApiConnector pentru a utiliza o metodă de inițializare:

În cadrul initialize metoda, am creat o variabilă de instanță pentru fiecare dintre parametri, astfel încât să putem utiliza aceste variabile și în alte părți ale aplicației.

Am eliminat și fișierul attr_accessor metoda de la noua initialize metoda se va ocupa de asta pentru noi. Dacă aveți nevoie de abilitatea de a apela elementele de date în afara clasei, atunci ar trebui totuși să aveți attr_accessor sună la loc.

Pentru a testa dacă initialize metoda funcționează, să creăm o altă metodă în cadrul clasei care tipărește aceste valori:

În cele din urmă, vom instanția clasa și vom testa metoda de inițializare:

[Out:]"My title""My cool description""https://next.tech"

Lucrul cu valori opționale

Acum, ce se întâmplă când vrem să facem una dintre aceste valori opțională? De exemplu, ce se întâmplă dacă dorim să acordăm o valoare implicită adresei URL? Pentru a face acest lucru, ne putem actualiza initialize metoda cu următoarea sintaxă:

Acum programul nostru va avea aceeași ieșire chiar dacă nu trecem url valoare în timp ce creați o nouă instanță a clasei:

Folosind argumente numite

Deși acest aspect pare simplu, argumentele trecătoare pot deveni complexe în aplicațiile Ruby din lumea reală, deoarece unele metode pot lua un număr mare de argumente. În astfel de cazuri, devine dificil să se cunoască ordinea argumentelor și ce valori să le atribuie.

Pentru a evita această confuzie, puteți utiliza argumente denumite, astfel:

Puteți introduce argumentele fără a fi nevoie să vă uitați la ordinea din initialize și chiar să schimbați ordinea argumentelor fără a provoca o eroare:

Anularea valorilor implicite

Ce se întâmplă dacă dorim să înlocuim o valoare implicită? Pur și simplu ne actualizăm apelul de instanțiere astfel:

Această actualizare va înlocui valoarea noastră implicită de https://next.tech, și sunând api.testing_initializer acum se va imprima https://next.xyz ca adresă URL.

Moştenire

Acum, vom învăța despre un important principiu orientat pe obiecte numit moştenire. Înainte de a intra în modul în care este executat în Ruby, să vedem de ce este important pentru construirea aplicațiilor.

Pentru început, moștenirea înseamnă că clasele dvs. pot avea o ierarhie. Este cel mai bine folosit atunci când diferite clase au unele responsabilități comune, deoarece ar fi o practică slabă să dublăm codul în fiecare clasă pentru un comportament identic sau chiar similar.

Ia-o pe a noastră ApiConnector clasă. Să presupunem că avem clase API diferite pentru diferite platforme, dar fiecare clasă partajează o serie de date sau procese comune. În loc să duplicăm codul în fiecare dintre clasele de conector API, putem avea unul clasa părinte cu datele și metodele partajate. De acolo, putem crea cursuri pentru copii din această clasă părinte. Cu modul în care funcționează moștenirea, fiecare dintre clasele copil va avea acces la componentele furnizate din clasa părinte.

De exemplu, să presupunem că avem trei API-uri: SmsConnector, PhoneConnector, și MailerConnector. Dacă am scrie cod individual pentru fiecare dintre aceste clase, ar arăta astfel:

După cum puteți vedea, repetăm ​​pur și simplu același cod în diferite clase. Aceasta este considerată o practică slabă de programare care încalcă USCAT (Nu te repeta) principiul dezvoltării. În schimb, putem face un ApiConnector clasa părinte și fiecare dintre celelalte clase poate moșteni funcționalitatea comună din această clasă:

Folosind moștenirea, am reușit să tăiem tot codul duplicat de-a lungul orelor noastre.

Sintaxa pentru utilizarea moștenirii este de a defini numele clasei copil, urmat de < simbol, apoi numele clasei părinte – adică our SmsConneclar, MailerConnector, and PhoneConnecclasele tor moștenesc de la the ApiConnecclasa tor.

Fiecare dintre aceste clase copil are acum acces la setul complet de elemente furnizate în părinte ApiConnector clasă. De exemplu, dacă creăm o nouă instanță a SmsConnector cu următorii parametri, putem apela send_sms metodă:

[Out:]Sending SMS message with the title 'Hi there!' and description 'I'm an SMS message'.

O regulă generală în PO este de a vă asigura că o clasă îndeplinește o singură responsabilitate. De exemplu, ApiConnector clasa nu ar trebui să trimită mesaje SMS, să efectueze apeluri telefonice sau să trimită e-mailuri, deoarece acestea ar fi trei responsabilități esențiale.

Metode private și publice

Înainte de a ne scufunda în metode private și publice, să ne întoarcem mai întâi la originalul nostru ApiConnector clasa și creați un SmsConnector clasă care moștenește din ApiConnector. În această clasă, vom crea o metodă numită send_sms care va rula un script care contactează un API:

Această metodă va trimite un title și url către un API, care la rândul său va trimite un mesaj SMS. Acum putem instanția SmsConnector clasa și sunați la send_sms mesaj:

Rularea acestui cod va contacta API-ul SMS și va trimite mesajul. Puteți merge în partea de jos a această pagină sa-ti vada mesajul!

Acum, folosind acest exemplu, să discutăm tipurile de metode oferite de clase.

send_sms metoda este o metoda publica. Aceasta înseamnă că oricine lucrează la clasa noastră poate comunica cu această metodă. S-ar putea să nu pară mare lucru dacă lucrați la o aplicație la care nimeni altcineva nu lucrează. Cu toate acestea, dacă creați o API sau o bibliotecă de coduri care este deschisă pentru ca alții să o folosească, este vital ca metodele dvs. publice să reprezinte elemente de funcționalitate pe care doriți să le folosească de fapt alți dezvoltatori.

Metodele publice ar trebui să fie rareori modificate. Acest lucru se datorează faptului că alți dezvoltatori se pot baza pe metodele dvs. publice pentru a fi consecvente, iar o modificare a unei metode publice poate rupe componentele programelor lor.

Deci, dacă nu puteți schimba metodele publice, cum puteți lucra la o aplicație de producție? Acolo este metode private intră. O metodă privată este o metodă accesată doar de clasa în care se află. Nu ar trebui să fie apelată niciodată de servicii externe. Aceasta înseamnă că le puteți modifica comportamentul, presupunând că aceste modificări nu au un efect domino și modifică metodele publice de la care ar putea fi apelate.

De obicei, metodele private sunt plasate la sfârșitul fișierului după toate metodele publice. Pentru a desemna metode private, folosim private cuvânt deasupra listei de metode. Să adăugăm o metodă privată la a noastră ApiConnector clasă:

Observați cum apelăm această metodă din interiorul initialize metoda ApiConnector clasă? Dacă rulăm acest cod, acesta va da următoarea ieșire:

[Out:]A secret message from the parent class

Acum, clasele pentru copii au acces la metodele din clasa părinte, nu? Ei bine, nu întotdeauna. Să eliminăm secret_method metoda din initialize metoda în ApiConnector și încercați să-l numiți de la al nostru SmsConnector clasa pentru copii, așa cum se arată aici:

[Out:]Traceback (most recent call last):main.rb:29:in `<main>': private method `secret_method' called for #SmsConnector:0x000056188cfe19b0> (NoMethodError)

Acest lucru se datorează faptului că SmsConnector class are acces doar la metodele publice din clasa părinte. Metodele private sunt, prin natura lor, private. Aceasta înseamnă că pot fi accesate numai de clasa în care sunt definite.

Deci, o regulă bună este crearea de metode private atunci când acestea nu ar trebui utilizate în afara clasei și metode publice atunci când acestea trebuie să fie disponibile în întreaga aplicație sau utilizate de servicii externe.

Înfășurându-se

Sper că v-a plăcut acest tutorial rapid despre conceptele fundamentale ale programării orientate pe obiecte în Ruby! Am acoperit crearea de clase, accesorii de atribute, instanțierea, inițializarea, moștenirea și metodele private și publice.

Ruby este un limbaj puternic orientat obiect folosit de aplicațiile populare, inclusiv a noastră aici, la Next Tech. Cu aceste cunoștințe fundamentale despre OOP, sunteți pe cale să vă dezvoltați propriile aplicații Ruby!

Dacă sunteți interesat să aflați mai multe despre programarea cu Ruby, consultați cursul nostru Introducere în Ruby Aici! În acest curs acoperim abilități de programare de bază, cum ar fi variabile, șiruri, bucle și condiționale, subiecte OOP mai avansate și gestionarea erorilor.