CodeGym/Blog Java/Aleatoriu/Concepte POO în Java
John Squirrels
Nivel
San Francisco

Concepte POO în Java

Publicat în grup
Unul dintre cele mai mari puncte forte ale Java este programarea orientată pe obiecte (OOP). Acesta este motivul pentru care acest limbaj a devenit atât de popular și este foarte potrivit pentru proiecte de orice dimensiune. Ce este programarea orientată pe obiecte? Nu este magie, dar poate părea magic dacă intrați cu adevărat în ea. OOP este despre cum să vă construiți software-ul. Este un concept, sau mai degrabă o grămadă de concepte oop în Java, care vă permit să creați unele interacțiuni și relații specifice între obiectele Java pentru a dezvolta și utiliza eficient software-ul. Concepte POO în Java - 1OOP clasică include 3 + 1 concepte principale. Să începem cu clasicii.

Obiectul

Obiectele Java, precum și obiectele din lumea reală au două caracteristici: stare și comportament.

De exemplu, un obiect uman are stare (nume, sex, somn sau nu...) și comportament (studiază Java, plimbă, vorbește...). Orice obiect Java își stochează starea în câmpuri și își expune comportamentul prin metode.

Încapsulare

Încapsularea datelor ascunde datele interne din lumea exterioară și accesarea acestora numai prin metode expuse public. Ce înseamnă asta? Ce date? Ascunderea de cine? Ascunderea înseamnă a restricționa accesul direct la membrii de date (câmpurile) unei clase.

Cum funcționează în Java:

  1. Câmpurile sunt private
  2. Fiecare câmp dintr-o clasă primește două metode speciale: un getter și un setter. Metodele getter returnează valoarea câmpului. Metodele de setare vă permit să modificați valoarea câmpului într-un mod indirect, dar permis.

Exemplu de încapsulare în cod Java:

public class Student {
private int age;
private String name;

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

public class Test{
public static void main(String[] args) {
Student firstStudent = new Student();
firstStudent.setName("John");
// The name field is private, so you can no longer do this:  firstStudent.name = "John";
}
}

De ce ar trebui să folosiți încapsularea?

Motivul principal este de a facilita schimbarea codului. Imaginați-vă că aveți o aplicație pentru o școală de hochei și există o clasă HockeyStudent cu două câmpuri care stochează numele și vârsta elevului când s-a înscris la școală. Ceva de genul:
public class HockeyStudent {
public String name;
public  int ageOfEnrollment;
}
Câmpul ageOfEnrollment este public, fără getters sau setters... Această clasă este folosită de multe alte clase și totul a fost ok până când un dezvoltator a decis că un singur câmp int nu este suficient. Unii jucători de hochei dintr-o cohortă sunt cu aproape un an mai în vârstă decât colegii lor, așa că ar fi mai convenabil să-i împărțiți în două grupuri, în funcție de luna în care s-au născut. Deci câmpul ageOfEnrollment ar trebui schimbat într-o matrice int (int[][]) : primul număr este pentru ani întregi, iar al doilea este pentru luni. Acum trebuie să refactorizezi tot codul care folosește clasa Student ! Dar dacă vârsta ta de înscrierecâmpul este privat și aveți getters și setters, atunci totul este mai ușor. Dacă se modifică cerința de setare a vârstei unui student, trebuie doar să actualizați logica în metoda setAgeOfEnrollment() și cursurile dvs. pot continua să folosească Student fără probleme! Acest exemplu este oarecum artificial, dar sper că explică de ce utilizarea încapsulării este o idee grozavă.

Moştenire

Acest principiu este mai ușor de înțeles chiar și fără nicio experiență practică. Nu te repeta (USCAT) ar putea fi motto-ul conceptului de moștenire. Moștenirea vă permite să creați o clasă copil care moștenește câmpurile și metodele clasei părinte fără a le redefini. Sigur, puteți suprascrie câmpurile și metodele clasei părinte în clasa copil, dar nu este o necesitate. În plus, puteți adăuga noi stări și comportamente în clasa de copii. Clasele părinte sunt uneori numite superclase sau clase de bază, iar clasele copil sunt cunoscute ca subclase. Cuvântul cheie Java extensis este folosit pentru a implementa principiul moștenirii în cod.

Cum funcționează în Java:

  1. Creați clasa părinte.
  2. Creați clasa copil folosind cuvântul cheie extins .
  3. În constructorul clasei Child, utilizați metoda super(parentField1, parentField2, ...) pentru a seta câmpurile părintelui.

Un constructor este o metodă specială folosită pentru a inițializa un obiect nou creat. Un constructor are același nume cu numele clasei sale. Există două tipuri de constructori: implicit (constructor fără argument) și constructor parametrizat. O clasă trebuie să aibă cel puțin un constructor (are constructorul implicit dacă nu au fost definiți alți constructori) și poate avea mulți dintre ei.

De fiecare dată când creați un obiect nou, îl apelați pe constructor. În exemplul de mai sus, faceți acest lucru în această linie:

Student firstStudent = new Student();

Folosiți noul cuvânt cheie pentru a apela constructorul implicit al clasei Student : tudent() .

Câteva reguli:

  1. O clasă poate avea un singur părinte.
  2. O clasă părinte poate avea mai multe clase de copii.
  3. O clasă de copii poate avea propriile clase de copii.

Exemplu de moștenire în cod Java

Să creăm o clasă de telefon .
public class Phone {
    int price;
    double weight;

// Constructor
public Phone(int price, double weight) {
        this.price = price;
        this.weight = weight;
    }

    void orderPhone(){
        System.out.println("Ordering phone...");
    }
}
Desigur, există diferite tipuri de telefoane, așa că haideți să creăm două clase de copii: una pentru telefoanele Android și una pentru iPhone. Apoi vom adăuga câteva câmpuri și metode pe care părintele nu le are. Și vom folosi super() pentru a apela constructorii pentru a inițializa câmpurile pe care le are clasa părinte.

Exemplu de moștenire în Java

public class Android extends Phone {

// Some new fields
String androidVersion;
int screenSize;

    String secretDeviceCode;

// Constructor
    public Android(int price, double weight, String androidVersion, int screenSize, String secretDeviceCode) {
        super(price, weight); // Android inherits Phone’s fields

        //this - reference to the current object
        //super - reference to the parent object

        this.androidVersion = androidVersion;
        this.screenSize = screenSize;
        this.secretDeviceCode = secretDeviceCode;
    }

	// New Android-specific method, does not exist in the Phone class
    void installNewAndroidVersion() {
        System.out.println("installNewAndroidVersion invoked...");

    }

}

public class IPhone extends Phone {

    boolean fingerPrint;

    public IPhone(int price, double weight, boolean fingerPrint) {
        super(price, weight);
        System.out.println("IPhone constructor was invoked...");
        this.fingerPrint = fingerPrint;
    }

    void deleteIPhoneFromDb() {
        System.out.println("deleteIPhoneFromDb invoked...");
    }

@Override // This is about polymorphism, see below
void orderPhone(){
        System.out.println("Ordering my new iPhone and deleting the old one...");
    }
}
Deci, repet: în Java, moștenirea vă permite să extindeți o clasă cu clase copil care moștenesc câmpurile și metodele clasei părinte. Este o modalitate excelentă de a obține reutilizarea codului.

Polimorfism

Polimorfismul este capacitatea unui obiect de a se transforma, luând forme diferite sau mai degrabă acționând în moduri diferite. În Java, polimorfismul se întâmplă de obicei atunci când o referință de clasă părinte este folosită pentru a se referi la un obiect de clasă copil.

Ce înseamnă asta și cum funcționează în Java:

Ce este polimorfismul în Java? În general, asta înseamnă că puteți folosi același nume de metodă în scopuri diferite. Există două tipuri de polimorfism în Java: suprascrierea metodei (polimorfism dinamic) și supraîncărcarea metodei (polimorfism static).

Anularea metodei

Puteți suprascrie metoda unei clase părinte într-o clasă copil, forțând-o să funcționeze într-un mod diferit. Să creăm o clasă părinte Muzician cu o metodă play() .

Exemplu de polimorfism în codul Java

public class Musician {
    String name;
    int age;

    // Default constructor
    public Musician() {
    }

    // Parameterized constructor
    public Musician(String name, int age) {
        this.name = name;
        this.age = age;
    }

    void play() {
        System.out.println("I am playing my instrument...");
    }
}
Muzicieni diferiți folosesc instrumente diferite. Să creăm două clase pentru copii: Pianist și Violonist . Datorită polimorfismului, fiecare va executa propria versiune a metodei play() . Când înlocuiți, puteți utiliza adnotarea @Override , dar nu este necesar.
public class Pianist extends Musician {

    String favoritePianoType;

    public Pianist(String name, int age, String favoritePianoType) {
        super(name, age);
        this.favoritePianoType = favoritePianoType;
    }


    @Override
void play(){
        System.out.println("I am playing the piano...");
    }
}
Vioara poate fi solist sau membru al unei orchestre. Să luăm acest lucru în considerare atunci când trecem peste metoda noastră play() .
public class Violinist extends Musician {
    boolean isSoloist;

public Violinist(String name, int age, boolean isSoloist) {
            super(name, age);
            this.isSoloist = isSoloist;
        }


    @Override
void play(){
if (isSoloist)
        System.out.println("I am playing the violin solo...");
else
System.out.println("I am playing the violin in an orchestra...");

    }
}
Să creăm o clasă Demo , în care vom crea trei obiecte, câte o instanță a fiecăreia dintre clasele create anterior. Vom vedea ce rezultate avem.
public class Demo {
  public static void main(String[] args) {
  Musician musician = new Musician();
  Violinist violinist = new Violinist("John", 32, true);
  Pianist pianist = new Pianist("Glen", 30, "Acoustic");

  System.out.println("Musician said:");
  musician.play();
  System.out.println("Violinist said:");
  violinist.play();
  System.out.println("Pianist said:");
  pianist.play();
    }
}
Iată ce primim:
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo…
Pianist said:
I am playing the piano...
Fiecare violonist și pianist este muzician, dar nu orice muzician este violist sau pianist. Asta înseamnă că poți folosi metoda de joc a muzicianului dacă nu trebuie să creezi una nouă. Sau puteți apela metoda părintelui de la copil folosind cuvântul cheie super . Să facem asta în codul Pianist:
public class Pianist extends Musician {

    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
}
Acum să apelăm metoda noastră main() în clasa Demo . Iată rezultatul:
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...

Supraîncărcarea metodei

Supraîncărcarea metodelor înseamnă utilizarea diferitelor metode cu același nume în aceeași clasă. Ele trebuie să fie diferite în ceea ce privește numărul, ordinea sau tipurile parametrilor lor. Să presupunem că un pianist poate cânta la pian acustic și la un pian electric. Pentru a cânta un electric, muzicianul are nevoie de electricitate. Să creăm două metode diferite play() . Prima fără parametri, pentru un pian acustic, iar a doua cu un parametru care indică dacă este disponibilă curent electric.
public class Pianist extends Musician {

    String name;
    int age;
    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
    void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            System.out.println("I am playing the piano...");
        }
        else System.out.println("I can't play this without electricity.");
    }
}
Apropo, puteți folosi prima metodă play() în cadrul celei de-a doua metode play(boolean) în acest fel:
void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            play();
        }
        else System.out.println("I can't play this without electricity.");
    }
Să adăugăm câteva rânduri la clasa noastră Demo pentru a demonstra supraîncărcarea noastră:
public class Demo {
    public static void main(String[] args) {

        Musician musician = new Musician();
        Violinist violinist = new Violinist("John", 23, true);
        Pianist pianist = new Pianist("Glen", 30, "Acoustic");

        System.out.println("Musician said:");
        musician.play();
        System.out.println("Violinist said:");
        violinist.play();
        System.out.println("Pianist said:");
        pianist.play();
        System.out.println("The pianist will now try the electric piano:");
        pianist.play(true);
        System.out.println("The electricity has been shut off. Now when trying the electric piano, the pianist says:");
        pianist.play(false);
    }
}
Iată rezultatul:
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...
The pianist will now try the electric piano:
The electricity is on.
I am playing my instrument...
I am playing the piano...
The electricity has been shut off. Now when trying the electric piano, the pianist says:
I can't play this without electricity.
Java știe ce metodă ar trebui utilizată pe baza parametrilor săi și a tipului de obiect. Asta e polimorfism.

Abstracția

Când definim o clasă, încercăm să construim un model de ceva. De exemplu, să presupunem că scriem un joc video numit MyRacer cu diferite mașini de curse. Un jucător poate alege unul dintre ele și apoi îl poate actualiza ulterior sau poate cumpăra unul diferit. Deci... Ce este o mașină? O mașină este un lucru destul de complicat, dar dacă încercăm să creăm un joc video de curse (spre deosebire de un simulator de conducere), atunci nu trebuie să descriem toate miile de viteze și garnituri pe care le conține. Avem nevoie de modelul, viteza maximă, caracteristicile de manevrabilitate, prețul, culoarea... Și poate că este suficient. Acesta este modelul unei mașini pentru jocul nostru. Mai târziu, în MyRacer 2, să presupunem că decidem să adăugăm anvelope care afectează manevrabilitatea pe drum. Aici modelul este diferit, pentru că am adăugat mai multe detalii. Lăsa' s definesc abstractizarea datelor ca fiind procesul de identificare numai a caracteristicilor importante (sau necesare) ale unui obiect și ignorarea oricăror detalii irelevante. Există diferite niveluri de abstractizare. De exemplu, dacă ești pasager într-un autobuz, trebuie să știi cum arată autobuzul tău și unde se duce, dar nu trebuie să știi cum să-l conduci. Dacă sunteți șofer de autobuz, nu trebuie să știți cum să creați un autobuz nou - trebuie doar să știți cum să îl conduceți. Dar dacă sunteți producător de autobuze, trebuie să treceți la un nivel inferior de abstractizare, deoarece detaliile designului autobuzului sunt foarte importante pentru dvs. Sper că înțelegi ce zic. trebuie să știi cum arată autobuzul tău și unde merge, dar nu trebuie să știi cum să-l conduci. Dacă sunteți șofer de autobuz, nu trebuie să știți cum să creați un autobuz nou - trebuie doar să știți cum să îl conduceți. Dar dacă sunteți producător de autobuze, trebuie să treceți la un nivel inferior de abstractizare, deoarece detaliile designului autobuzului sunt foarte importante pentru dvs. Sper că înțelegi ce zic. trebuie să știi cum arată autobuzul tău și unde merge, dar nu trebuie să știi cum să-l conduci. Dacă sunteți șofer de autobuz, nu trebuie să știți cum să creați un autobuz nou - trebuie doar să știți cum să îl conduceți. Dar dacă sunteți producător de autobuze, trebuie să treceți la un nivel inferior de abstractizare, deoarece detaliile designului autobuzului sunt foarte importante pentru dvs. Sper că înțelegi ce zic.

Cum funcționează în Java:

Să construim patru niveluri de abstractizare în Java, sau mai degrabă în OOP — de la cel mai scăzut (cel mai specific) la cel mai înalt (cel mai abstract).
  1. Cel mai de jos nivel de abstractizare este un obiect specific. Este o entitate cu un set de caracteristici care aparțin unei clase specifice. Are valori specifice de câmp

  2. Un șablon pentru crearea de obiecte este o clasă. Este o descriere a unui set de obiecte cu proprietăți similare și structură internă.

  3. O clasă abstractă este o descriere abstractă a caracteristicilor unui set de clase (acționează ca un șablon pentru moștenirea de către alte clase). Are un nivel ridicat de abstractizare, deci este imposibil să creezi obiecte direct dintr-o clasă abstractă. Pentru a crea obiecte pot fi folosite numai clasele copil de clase abstracte. O clasă abstractă poate include metode cu o implementare, dar aceasta nu este o cerință.

  4. O interfață este un construct al limbajului de programare Java care conține doar metode publice abstracte și câmpuri constante statice (static final). Cu alte cuvinte, nici clasele abstracte, nici interfețele nu pot fi folosite pentru a genera obiecte.

BTW, în Java 8 sau mai târziu, interfețele pot avea nu numai metode abstracte și constante, ci și metode implicite și statice. În Java, o interfață definește un comportament, în timp ce o clasă abstractă este folosită pentru a crea o ierarhie. O interfață poate fi implementată de mai multe clase.

Exemplu de interfață în cod Java

interface Human {
	public void struggle();
	public void protect();
}

interface Vulcan {
	int angleOfPointyEars;
	public void turnOffEmotions(boolean isOn);
	public void telepathy();
}
Puteți implementa mai mult de o interfață
The Spock class implements Human and Vulcan {
public void struggle() {
System.out.println("I am struggling...");
}
	public void protect() {
System.out.println("You are under my protection!);
}
public void turnOffEmotions(boolean isOn){
If (isOn) {
System.out.println("I am turning off my emotions.");
isOn= !isOn;
}
}
	public void telepathy() {
System.out.println("Connecting to your brain...");
}

}
Pentru studenții începători, acesta acoperă toate conceptele principale de programare orientată pe obiecte în Java. Pe lângă cele 4 principii principale OOP, Java are și asociere, agregare și compoziție. Le puteți numi „principii OOP suplimentare”. Merită propriul lor articol separat.
Comentarii
  • Popular
  • Nou
  • Vechi
Trebuie să fii conectat pentru a lăsa un comentariu
Această pagină nu are încă niciun comentariu