CodeGym /Blog Java /Aleatoriu /Principiile POO
John Squirrels
Nivel
San Francisco

Principiile POO

Publicat în grup
Java este un limbaj orientat pe obiecte. Aceasta înseamnă că trebuie să scrieți programe Java folosind o paradigmă orientată pe obiecte. Și această paradigmă presupune utilizarea obiectelor și claselor în programele dumneavoastră. Să încercăm să folosim exemple pentru a înțelege ce sunt clasele și obiectele și cum să aplicăm principiile de bază OOP (abstracție, moștenire, polimorfism și încapsulare) în practică.

Ce este un obiect?

Lumea în care trăim este formată din obiecte. Privind în jur, putem vedea că suntem înconjurați de case, copaci, mașini, mobilier, vase și computere. Toate aceste lucruri sunt obiecte și fiecare dintre ele are un set de caracteristici, comportamente și scopuri specifice. Suntem obișnuiți cu obiectele și le folosim întotdeauna în scopuri foarte specifice. De exemplu, dacă trebuie să mergem la serviciu, folosim o mașină. Dacă vrem să mâncăm, folosim feluri de mâncare. Iar dacă vrem să ne odihnim, găsim o canapea confortabilă. Oamenii sunt obișnuiți să gândească în termeni de obiecte pentru a rezolva problemele din viața de zi cu zi. Acesta este unul dintre motivele pentru care obiectele sunt folosite în programare. Această abordare se numește programare orientată pe obiecte. Să dăm un exemplu. Imaginați-vă că ați dezvoltat un nou telefon și doriți să începeți producția de masă. În calitate de dezvoltator al telefonului, știi pentru ce este, cum funcționează și care sunt părțile sale (corp, microfon, difuzor, fire, butoane etc.). În plus, doar tu știi cum să conectezi aceste părți. Dar nu intenționați să faceți telefoanele personal – aveți o întreagă echipă de lucrători care să facă acest lucru. Pentru a elimina necesitatea de a explica în mod repetat cum să conectați piesele telefonului și pentru a vă asigura că toate telefoanele sunt realizate în același mod, înainte de a începe să le produceți, trebuie să faceți un desen care să descrie modul în care este organizat telefonul. În OOP, numim o astfel de descriere, desen, diagramă sau șablon o clasă. Acesta formează baza creării de obiecte atunci când programul rulează. O clasă este o descriere a obiectelor de un anumit tip - ca un șablon comun format din câmpuri, metode și un constructor. Un obiect este o instanță a unei clase.

Abstracția

Să ne gândim acum la modul în care putem trece de la un obiect din lumea reală la un obiect dintr-un program. Vom folosi telefonul ca exemplu. Acest mijloc de comunicare are o istorie care se întinde pe mai mult de 100 de ani. Telefonul modern este un dispozitiv mult mai complex decât predecesorul său din secolul al XIX-lea. Când folosim telefonul, nu ne gândim la organizarea acestuia și la procesele care au loc în interiorul acestuia. Pur și simplu folosim funcțiile oferite de dezvoltatorii telefonului: butoane sau un ecran tactil pentru a introduce un număr de telefon și a efectua apeluri. Una dintre primele interfețe de telefon a fost o manivelă care trebuia rotită pentru a efectua un apel. Desigur, acest lucru nu a fost foarte convenabil. Dar și-a îndeplinit funcția impecabil. Dacă comparați cele mai moderne și primele telefoane, puteți identifica imediat funcțiile cele mai importante pentru dispozitivul de la sfârșitul secolului al XIX-lea și pentru smartphone-ul modern. Acestea sunt capacitatea de a efectua apeluri și capacitatea de a primi apeluri. De fapt, acesta este ceea ce face telefonul un telefon, și nu altceva. Acum tocmai am aplicat un principiu al OOP: identificați cele mai importante caracteristici și informații ale unui obiect. Acest principiu se numește abstractizare. În OOP, abstracția poate fi definită și ca o metodă de reprezentare a elementelor unei sarcini din lumea reală ca obiecte într-un program. Abstracția este întotdeauna asociată cu generalizarea anumitor proprietăți ale unui obiect, deci principalul lucru este să separați informațiile semnificative de cele nesemnificative în contextul sarcinii în cauză. În plus, pot exista mai multe niveluri de abstractizare. Lăsa' Încercăm să aplicăm principiul abstracției pe telefoanele noastre. Pentru început, vom identifica cele mai comune tipuri de telefoane - de la primele telefoane până la cele din zilele noastre. De exemplu, le-am putea reprezenta sub forma diagramei din Figura 1. Principiile POO - 2Folosind abstractizarea, putem identifica acum informațiile generale din această ierarhie a obiectelor: obiectul general abstract (telefonul), caracteristicile comune ale telefonului (de exemplu anul creării sale) și interfața comună (toate telefoanele pot primi și efectua apeluri). Iată cum arată în Java:

public abstract class AbstractPhone {
    private int year;

    public AbstractPhone(int year) {
        this.year = year;
    }
    public abstract void call(int outgoingNumber);
    public abstract void ring(int incomingNumber);
}
Într-un program, putem crea noi tipuri de telefoane folosind această clasă abstractă și aplicând alte principii de bază ale OOP, pe care le vom explora mai jos.

Încapsulare

Cu abstractizarea, identificăm ceea ce este comun pentru toate obiectele. Dar fiecare tip de telefon este unic, diferă cumva de celelalte. Într-un program, cum trasăm limite și cum identificăm această individualitate? Cum facem ca nimeni să nu ne poată sparge accidental sau deliberat telefonul sau să încerce să transforme un model în altul? În lumea reală, răspunsul este evident: trebuie să puneți toate piesele într-o husă pentru telefon. La urma urmei, dacă nu - lăsând în schimb toate părțile interne ale telefonului și firele de conectare în exterior - un experimentator curios va dori cu siguranță să ne „îmbunătățească” telefonul. Pentru a preveni o astfel de modificare, principiul încapsulării este utilizat în proiectarea și funcționarea unui obiect. Acest principiu afirmă că atributele și comportamentul unui obiect sunt combinate într-o singură clasă, obiectul' Implementarea internă a lui este ascunsă utilizatorului și este furnizată o interfață publică pentru lucrul cu obiectul. Sarcina programatorului este de a determina care dintre atributele și metodele unui obiect ar trebui să fie disponibile pentru acces public și care sunt detaliile interne de implementare care ar trebui să fie inaccesibile.

Încapsulare și control acces

Să presupunem că informațiile despre un telefon (anul său de producție sau sigla producătorului) sunt gravate pe spate atunci când este realizat. Informația (starea acesteia) este specifică acestui model particular. Putem spune că producătorul s-a asigurat că această informație este imuabilă - este puțin probabil ca cineva să se gândească să elimine gravura. În lumea Java, o clasă descrie starea obiectelor viitoare folosind câmpuri, iar comportamentul lor este descris folosind metode. Accesul la starea și comportamentul unui obiect este controlat folosind modificatori aplicați câmpurilor și metodelor: privat, protejat, public și implicit. De exemplu, am decis că anul de producție, numele producătorului și una dintre metode sunt detalii interne de implementare ale clasei și nu pot fi modificate de alte obiecte din program. În cod,

public class SomePhone {

    private int year;
    private String company;
    public SomePhone(int year, String company) {
        this.year = year;
        this.company = company;
    }
private void openConnection(){
    // findSwitch
    // openNewConnection...
}
public void call() {
    openConnection();
    System.out.println("Calling");
}

public void ring() {
    System.out.println("Ring-ring");
}

 }
Modificatorul privat permite accesarea câmpurilor și metodelor clasei numai în cadrul acestei clase. Aceasta înseamnă că este imposibil să accesezi câmpuri private din exterior, deoarece metodele private nu pot fi apelate. Restricționarea accesului la metoda openConnection ne lasă, de asemenea, posibilitatea de a schimba liber implementarea internă a metodei, deoarece metoda este garantată să nu fie utilizată de sau să întrerupă activitatea altor obiecte. Pentru a lucra cu obiectul nostru, lăsăm disponibile metodele de apel și apel folosind modificatorul public. Furnizarea de metode publice de lucru cu obiecte este, de asemenea, parte a încapsulării, deoarece dacă accesul ar fi refuzat complet, ar deveni inutil.

Moştenire

Să aruncăm o altă privire asupra diagramei telefoanelor. Puteți vedea că este o ierarhie în care un model are toate caracteristicile modelelor situate mai sus de-a lungul ramurii sale și adaugă unele dintre ele. De exemplu, un smartphone folosește o rețea celulară pentru comunicare (are proprietățile unui telefon mobil), este wireless și portabil (are proprietățile unui telefon fără fir) și poate primi și efectua apeluri (are proprietățile unui telefon). Ceea ce avem aici este moștenirea proprietăților obiectului. În programare, moștenirea înseamnă utilizarea claselor existente pentru a defini altele noi. Să luăm în considerare un exemplu de utilizare a moștenirii pentru a crea o clasă de smartphone. Toate telefoanele fără fir sunt alimentate de baterii reîncărcabile, care au o anumită durată de viață. În consecință, adăugăm această proprietate la clasa de telefon fără fir:

public abstract class CordlessPhone extends AbstractPhone {

    private int hour;

    public CordlessPhone (int year, int hour) {
        super(year);
        this.hour = hour;
    }
    }
Telefoanele mobile moștenesc proprietățile unui telefon fără fir și implementăm metodele de apel și apel în această clasă:

public class CellPhone extends CordlessPhone {
    public CellPhone(int year, int hour) {
        super(year, hour);
    }

    @Override
    public void call(int outgoingNumber) {
        System.out.println("Calling " + outgoingNumber);
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("Incoming call from " + incomingNumber);
    }
}
Și, în sfârșit, avem clasa de smartphone, care, spre deosebire de telefoanele mobile clasice, are un sistem de operare cu drepturi depline. Puteți extinde funcționalitatea smartphone-ului dvs. adăugând noi programe care pot rula pe sistemul său de operare. În cod, clasa poate fi descrisă după cum urmează:

public class Smartphone extends CellPhone {
    
    private String operationSystem;

    public Smartphone(int year, int hour, String operationSystem) {
        super(year, hour);
        this.operationSystem = operationSystem;
    }
public void install(String program) {
    System.out.println("Installing " + program + " for " + operationSystem);
}

}
După cum puteți vedea, am creat un cod destul de nou pentru a descrie clasa Smartphone , dar am primit o clasă nouă cu funcționalități noi. Acest principiu al OOP face posibilă reducerea semnificativă a cantității de cod Java necesară, ușurând astfel viața programatorului.

Polimorfism

În ciuda diferențelor în aspectul și designul diferitelor tipuri de telefoane, putem identifica un comportament comun: toate pot primi și efectua apeluri și toate au un set de comenzi destul de clar și simplu. În ceea ce privește programarea, principiul abstractizării (cu care suntem deja familiarizați) ne lasă să spunem că obiectele telefonului au o interfață comună. De aceea, oamenii pot folosi cu ușurință diferite modele de telefoane care au aceleași comenzi (butoane mecanice sau un ecran tactil), fără a se adânci în detaliile tehnice ale dispozitivului. Astfel, folosești un telefon mobil în mod constant și poți efectua cu ușurință un apel de pe telefonul fix al prietenului tău. Principiul OOP care spune că un program poate folosi obiecte cu o interfață comună fără nicio informație despre structura internă a obiectului se numește polimorfism. Lăsa' Ne imaginăm că avem nevoie de programul nostru pentru a descrie un utilizator care poate folosi orice telefon pentru a apela un alt utilizator. Iată cum o putem face:

public class User {
    private String name;

    public User(String name) {
        this.name = name;
            }

    public void callAnotherUser(int number, AbstractPhone phone){
// And here's polymorphism: using the AbstractPhone type in the code!
        phone.call(number);
    }
}
 }
Acum vom descrie mai multe tipuri de telefoane. Unul dintre primele telefoane:

public class ThomasEdisonPhone extends AbstractPhone {

public ThomasEdisonPhone(int year) {
    super(year);
}
    @Override
    public void call(int outgoingNumber) {
        System.out.println("Crank the handle");
        System.out.println("What number would you like to connect to?");
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("The phone is ringing");
    }
}
Un telefon fix obișnuit:

public class Phone extends AbstractPhone {

    public Phone(int year) {
        super(year);
    }

    @Override
    public void call(int outgoingNumber) {
        System.out.println("Calling " + outgoingNumber);
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("The phone is ringing");
    }
}
Și în sfârșit, un telefon video tare:

public class VideoPhone extends AbstractPhone {

    public VideoPhone(int year) {
        super(year);
    }
    @Override
    public void call(int outgoingNumber) {
        System.out.println("Connecting video call to " + outgoingNumber);
    }
    @Override
    public void ring(int incomingNumber) {
        System.out.println("Incoming video call from " + incomingNumber);
    }
  }
Vom crea obiecte în metoda main() și vom testa metoda callAnotherUser() :

AbstractPhone firstPhone = new ThomasEdisonPhone(1879);
AbstractPhone phone = new Phone(1984);
AbstractPhone videoPhone=new VideoPhone(2018);
User user = new User("Jason");
user.callAnotherUser(224466, firstPhone);
// Crank the handle
// What number would you like to connect to?
user.callAnotherUser(224466, phone);
// Calling 224466
user.callAnotherUser(224466, videoPhone);
// Connecting video call to 224466
Apelarea aceleiași metode pe obiectul utilizator produce rezultate diferite. O implementare specifică a metodei de apel este selectată dinamic în cadrul metodei callAnotherUser() pe baza tipului specific de obiect transmis când programul rulează. Acesta este principalul avantaj al polimorfismului – abilitatea de a alege o implementare în timpul execuției. În exemplele de clase de telefon prezentate mai sus, am folosit suprascrierea metodei — un truc în care schimbăm implementarea unei metode definite în clasa de bază fără a schimba semnătura metodei. Aceasta înlocuiește în esență metoda: noua metodă definită în subclasă este apelată atunci când programul este executat. De obicei, când suprascriem o metodă, @Overridese folosește adnotarea. Îi spune compilatorului să verifice semnăturile metodelor suprascrise și suprascrise. În cele din urmă, pentru a vă asigura că programele dvs. Java sunt în concordanță cu principiile OOP, urmați aceste sfaturi:
  • identificarea principalelor caracteristici ale unui obiect;
  • identificați proprietățile și comportamentul comune și utilizați moștenirea la crearea claselor;
  • utilizați tipuri abstracte pentru a descrie obiecte;
  • încercați să ascundeți întotdeauna metodele și câmpurile legate de implementarea internă a unei clase.
Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION