Object-oriented programming (OOP) si riferisce ad una metodologia di programmazione basata su oggetti, invece di semplici funzioni e procedure. Gli oggetti contengono i dati e i metodi (o il comportamento).

Nei concetti OOPs, impareremo quattro principi principali: astrazione, incapsulamento, ereditarietà e polimorfismo. Sono anche noti come quattro pilastri del paradigma di programmazione orientata agli oggetti.,

  1. L’astrazione è il processo di esposizione dei dettagli essenziali di un’entità, ignorando i dettagli irrilevanti, per ridurre la complessità per gli utenti.
  2. L’incapsulamento è il processo di raggruppamento dei dati e delle operazioni sui dati insieme in un’entità.
  3. L’ereditarietà viene utilizzata per derivare un nuovo tipo da un tipo esistente, stabilendo così una relazione padre-figlio.
  4. Il polimorfismo consente a un’entità di assumere significati diversi in contesti diversi.

Che cos’è la programmazione orientata agli oggetti?,

Nei primi giorni, i programmi sono stati scritti con codice binario, e interruttori meccanici sono stati utilizzati per caricare i programmi. Successivamente, con l’evolversi delle capacità hardware, gli esperti hanno cercato di semplificare la programmazione utilizzando linguaggi di alto livello in cui i compilatori venivano utilizzati per generare istruzioni macchina dal programma.

Con più evoluzione, gli esperti hanno creato la programmazione strutturata che si basava su piccole funzioni. Queste funzioni hanno aiutato in molti modi, ad esempio riutilizzo del codice, variabili locali, debug del codice e manutenibilità del codice.,

Con un maggiore avanzamento del calcolo e la richiesta di applicazioni più complesse, i limiti della programmazione strutturata hanno iniziato a essere visibili. Le applicazioni complesse dovevano essere più strettamente modellate con il mondo reale e i casi d’uso.

Poi gli esperti hanno sviluppato la programmazione orientata agli oggetti. Nel centro di OOP, abbiamo oggetti e classi., Proprio come un’entità reale, un oggetto ha due caratteri principali :

  • data – racconta gli attributi e lo stato dell’oggetto
  • comportamento – gli conferisce la capacità di cambiare se stesso e comunicare con altri oggetti

1.1. Classe e Oggetto

Un oggetto è un’istanza di una classe. Ogni oggetto ha il proprio stato, comportamento e identità. Una classe è il modello o modello per i suoi oggetti. Gli oggetti possono comunicare con altri oggetti chiamando le funzioni. A volte viene indicato come passaggio di messaggi.,

Ad esempio, se stiamo lavorando su un’applicazione HR, è costituita da entità/attori, ad esempio dipendente, manager, dipartimento, buste paga, ferie, obiettivi, monitoraggio del tempo, ecc. Per modellare queste entità nei programmi per computer, possiamo creare classi che avranno attributi e comportamenti di dati simili come nella vita reale.

Ad esempio, un’entità dipendente può essere rappresentata comeEmployee classe:

Il precedenteEmployee funge da modello. Possiamo usare questa classe per creare tanti oggetti dipendenti diversi di cui abbiamo bisogno nell’applicazione.,

Employee e = new Employee(111);e.setFirstName("Alex");....int age = e.getAge();

Il campo id aiuta a memorizzare e recuperare i dettagli di ogni singolo dipendente.

L’identità dell’oggetto viene generalmente mantenuta dall’Application Runtime environment, ad esempio per le applicazioni Java, la sua Java Virtual Machine (JVM). Ogni volta che creiamo un oggetto Java, JVM crea un hashcode per questo oggetto e lo assegna. In questo modo, anche se il programmatore dimentica di aggiungere il campo id, JVM assicura che tutti gli oggetti siano identificati in modo univoco.

1.2., Costruttore

I costruttori sono metodi speciali senza valore di ritorno. Il loro nome è sempre lo stesso del nome della classe; ma possono accettare parametri che aiutano a impostare lo stato iniziale dell’oggetto, prima che l’applicazione inizi ad usarlo.

Se non forniamo alcun costruttore, JVM assegna un costruttore predefinito alla classe. Questo costruttore predefinito non accetta alcun parametro.

Ricorda, se assegniamo un costruttore a qualsiasi classe, JVM non assegna il costruttore predefinito ad esso. Se necessario, dobbiamo specificare esplicitamente il costruttore predefinito nella classe.,

public class Employee { // Default constructor public Employee() { } // Custom constructor public Employee(int id) { this.id = id; }}

Quattro Principi della OOP

Le quattro principali caratteristiche della programmazione object oriented sono:

  • Astrazione
  • Incapsulamento
  • Ereditarietà
  • Polimorfismo
OOP Pilastri

2.1. Astrazione

L’astrazione è molto facile da capire quando la mettiamo in relazione con l’esempio in tempo reale. Ad esempio, quando guidiamo la nostra auto, non dobbiamo preoccuparci dell’esatto funzionamento interno dell’auto., Quello che ci interessa è interagire con l’auto tramite le sue interfacce come il volante, il pedale del freno, il pedale dell’acceleratore, ecc. Qui la conoscenza che abbiamo della macchina è astratta.

In informatica, l’astrazione è il processo mediante il quale dati e programmi sono definiti con una rappresentazione simile nella forma al suo significato (semantica) nascondendo i dettagli dell’implementazione.

In termini più semplici, l’astrazione consiste nel nascondere informazioni che non sono rilevanti per il contesto o piuttosto mostrano solo informazioni rilevanti e semplificarle confrontandole con qualcosa di simile nel mondo reale.,

Astrazione cattura solo quei dettagli su un oggetto che è rilevante per la prospettiva corrente.

In genere l’astrazione può essere vista in due modi:

  1. Astrazione dei dati

    L’astrazione dei dati è il modo per creare tipi di dati complessi da più tipi di dati più piccoli, che è più vicino alle entità reali. ad esempio una classe Employee può essere un oggetto complesso di avere varie piccole associazioni.,

    public class Employee { private Department department; private Address address; private Education education; //So on...}

    Quindi, se vuoi recuperare le informazioni di un dipendente, le chiedi dall’oggetto Employee – come fai nella vita reale, chiedi alla persona stessa.

  2. Astrazione di controllo

    L’astrazione di controllo si ottiene nascondendo la sequenza di azioni per un’attività complessa – all’interno di una semplice chiamata al metodo, quindi la logica per eseguire l’attività può essere nascosta dal client e potrebbe essere modificata in futuro senza influire sul codice del client.,

    public class EmployeeManager{ public Address getPrefferedAddress(Employee e) { //Get all addresses from database //Apply logic to determine which address is preferred //Return address }}

    Nell’esempio precedente, domani se si desidera modificare la logica in modo che ogni volta l’indirizzo domestico sia sempre l’indirizzo preferito, si cambierà la logica all’interno del metodogetPrefferedAddress() e il client non sarà influenzato.

Per saperne di più : Astrazione in Java

2.2. Incapsulamento

Il wrapping di dati e metodi all’interno delle classi in combinazione con l’occultamento dell’implementazione (attraverso il controllo degli accessi) è spesso chiamato incapsulamento., Il risultato è un tipo di dati con caratteristiche e comportamenti.

“Qualunque cosa cambi, incapsulalo” – Un famoso principio di progettazione

L’incapsulamento ha essenzialmente sia l’occultamento delle informazioni che l’occultamento dell’implementazione.

  • Informazioni nascondere è fatto attraverso l’utilizzo di modificatori di controllo di accesso (pubblico, privato, protetto) eimplementation hiding è ottenuto attraverso la creazione di interfaccia per una classe.
  • Implementazione nascondere dà al progettista la libertà di modificare il modo in cui la responsabilità è soddisfatta da un oggetto., Ciò è particolarmente utile nei punti in cui è probabile che il design (o anche i requisiti) cambino.

Facciamo un esempio per renderlo più chiaro.

2.2.1. Informazioni nascoste

class InformationHiding { //Restrict direct access to inward data private ArrayList items = new ArrayList(); //Provide a way to access data - internal logic can safely be changed in future public ArrayList getItems(){ return items; }}
2.2.2. Implementazione nascondere

interface ImplemenatationHiding { Integer sumAllItems(ArrayList items);}class InformationHiding implements ImplemenatationHiding{ //Restrict direct access to inward data private ArrayList items = new ArrayList(); //Provide a way to access data - internal logic can safely be changed in future public ArrayList getItems(){ return items; } public Integer sumAllItems(ArrayList items) { //Here you may do N number of things in any sequence //Which you do not want your clients to know //You can change the sequence or even whole logic //without affecting the client }}

Per saperne di più : Incapsulamento in Java

2.3. Ereditarietà

L’ereditarietà è un altro concetto importante nella programmazione orientata agli oggetti., L’ereditarietà in Java è un meccanismo mediante il quale una classe acquisisce le proprietà e i comportamenti della classe padre. Sta essenzialmente creando una relazione genitore-figlio tra le classi. In Java, useremo l’ereditarietà principalmente per la riusabilità e la manutenibilità del codice.

Parola chiave “estende” viene utilizzato per ereditare una classe in java. La parola chiave”” indica che stiamo creando una nuova classe che deriva da una classe esistente.

Nella terminologia di Java, una classe ereditata è chiamata super classe. La nuova classe è chiamata sottoclasse.,

Una sottoclasse eredita tutti i membri non privati (campi, metodi e classi nidificate) dalla sua superclasse. I costruttori non sono membri, quindi non sono ereditati dalle sottoclassi, ma il costruttore della superclasse può essere invocato dalla sottoclasse.

2.3.1., Esempio di ereditarietà
public class Employee { private Department department; private Address address; private Education education; //So on...}public class Manager extends Employee { private List<Employee> reportees;}

Nel codice di cui sopra, Manager è specializzata versione di Employee e riutilizza department address e education da Employee classe nonché definire il proprio reportees elenco.

3.2.2. Tipi di ereditarietà
  • Ereditarietà singola: una classe figlio deriva da una classe genitore.
    class Parent{ //code}class Child extends Parent{ //code}
  • Eredità multiple – Un figlio può derivare da più genitori. Fino a JDK 1.,7, l’ereditarietà multipla non era possibile in java attraverso l’uso di classi. Ma da JDK 1.8 in poi, l’ereditarietà multipla è possibile tramite l’uso di interfacce con metodi predefiniti.

    L’ereditarietà multipla attraverso l’uso di interfacce è sempre possibile in Java.

    interface MyInterface1{ }interface MyInterface2{ }class MyClass implements MyInterface1, MyInterface2{}
  • Ereditarietà multilivello: si riferisce all’ereditarietà tra più di tre classi in modo tale che una classe figlio funga da classe genitore per un’altra classe figlio.

    Nell’esempio dato, B è anche la classe genitore e la classe figlio.,

    class A{}class B extends A{}class C extends B{}
  • Ereditarietà gerarchica: si riferisce all’ereditarietà quando esiste una super classe e più sottoclassi che estendono la super classe.
    class A{}class B extends A{}class C extends A{}class D extends A{}
  • Ereditarietà ibrida-È una combinazione di due o più tipi di ereditarietà. Quindi, quando la relazione tra le classi contiene ereditarietà di due o più tipi, allora diciamo che le classi implementano l’ereditarietà ibrida.
    interface A{}interface B extends A{}class C implements A{}class D extends C impements B{}

2.4., Polimorfismo

Il polimorfismo è l’abilità con cui possiamo creare funzioni o variabili di riferimento che si comportano in modo diverso in un diverso contesto programmatico. Viene spesso indicato come un nome con molte forme.

Ad esempio, nella maggior parte dei linguaggi di programmazione, l’operatore '+' viene utilizzato per aggiungere due numeri e concatenare due stringhe. In base al tipo di variabili, l’operatore cambia il suo comportamento. È noto come sovraccarico dell’operatore.

In Java, il polimorfismo è essenzialmente considerato in due tipi:

2.4.1., Polimorfismo in fase di compilazione

Nel polimorfismo in fase di compilazione, il compilatore può associare i metodi appropriati ai rispettivi oggetti in fase di compilazione perché ha tutte le informazioni necessarie e sa quale metodo chiamare durante la compilazione del programma.

Viene spesso definito come il binding statico o il binding precoce.

In Java, si ottiene con l’uso del sovraccarico del metodo. In overloading del metodo, i parametri del metodo possono variare a seconda del numero, dell’ordine o dei tipi di parametro.

2.4.2., Polimorfismo di runtime

Nel polimorfismo di runtime, la chiamata a un metodo sovrascritto viene risolta dinamicamente in fase di runtime. L’oggetto, su cui verrà eseguito il metodo, viene determinato in fase di runtime, generalmente in base al contesto guidato dall’utente.

Viene spesso definito come il binding dinamico o il metodo di override. Potremmo averlo sentito con name dynamic method dispatch.

Nel polimorfismo di runtime, generalmente abbiamo una classe genitore e una classe figlio minima. In una classe, scriviamo una dichiarazione per eseguire un metodo che è presente nella classe genitore e nella classe figlio, entrambi.,

La chiamata al metodo viene data utilizzando la variabile del tipo di classe genitore. L’istanza effettiva della classe viene determinata in fase di runtime perché una variabile di tipo classe padre può memorizzare il riferimento all’istanza della classe padre e anche alla classe figlio.

Per saperne di più : Polimorfismo in java

Concetti minori

Oltre ai 4 elementi costitutivi di OOP precedenti, abbiamo alcuni altri concetti che svolgono un ruolo importante nella costruzione dell’intera comprensione.

Prima di approfondire, capiremo il termine modulo., Nella programmazione generale, un modulo si riferisce a una classe o una sotto-applicazione che eseguono funzionalità uniche. Nell’applicazione HR, una classe può eseguire varie funzioni come l’invio di e-mail, generare slittamento salariale, calcolare l’età del dipendente, ecc.

3.1. Accoppiamento

L’accoppiamento è la misura del grado di interdipendenza tra i moduli. Accoppiamento si riferisce a quanto fortemente un elemento software è collegato ad altri elementi. Un buon software avrà un accoppiamento basso.

Significa che una classe deve eseguire un’attività unica o solo attività indipendenti da altre attività. Ad esempio, una classeEmailValidator convaliderà solo l’e-mail. Analogamente,EmailSender classe invierà solo e-mail.

Se includiamo entrambe le funzionalità all’interno di una singola classeEmailUtils allora è un esempio di accoppiamento stretto.

3.2. Coesione

La coesione è la colla interna che tiene insieme il modulo. Una buona progettazione del software avrà un’elevata coesione.

Significa che una classe / modulo dovrebbe includere tutte le informazioni necessarie per svolgere la sua funzione senza alcuna dipendenza., Ad esempio, una classe EmailSender dovrebbe essere in grado di configurare il server SMTP, accettare l’e-mail, l’oggetto e il contenuto del mittente. Fondamentalmente, dovrebbe concentrarsi solo sull’invio di e-mail.

L’applicazione non deve utilizzare EmailSender per qualsiasi altra funzione diversa dall’invio di e-mail. La bassa coesione si traduce in classi monolitiche difficili da mantenere, comprendere e ridurre la riutilizzabilità.

3.3. Associazione

Associazione si riferisce alla relazione tra oggetti che hanno un ciclo di vita indipendente senza proprietà.,

Prendiamo un esempio di insegnante e studente. Più studenti possono associarsi a un singolo insegnante e un singolo studente può associarsi a più insegnanti, ma entrambi hanno i loro cicli di vita.

Entrambi possono essere creati e cancellati in modo indipendente in modo che quando un insegnante lascia la scuola, non abbiamo bisogno di eliminare gli studenti, e quando uno studente lascia la scuola, non abbiamo bisogno di eliminare gli insegnanti.

3.4. Aggregazione

L’associazione si riferisce alla relazione tra oggetti che hanno un ciclo di vita indipendente con proprietà., È tra le classi figlio e genitore in cui gli oggetti figlio non possono appartenere a un altro oggetto genitore.

Prendiamo un esempio di un telefono cellulare e una batteria del telefono cellulare. Una singola batteria può appartenere a un solo telefono alla volta. Se il telefono smette di funzionare e lo cancelliamo dal nostro database, la batteria del telefono non verrà eliminata perché potrebbe essere ancora funzionale. Quindi, in aggregazione, mentre esiste la proprietà, gli oggetti hanno il loro ciclo di vita.

3.5. Composizione

Composizione si riferisce alle relazioni quando gli oggetti non hanno un ciclo di vita indipendente., Se l’oggetto padre viene eliminato, verranno eliminati anche tutti gli oggetti figlio.

Ad esempio, la relazione tra domande e risposte. Le singole domande possono avere più risposte, ma le risposte non possono appartenere a più domande. Se cancelliamo una domanda, tutte le sue risposte verranno automaticamente eliminate.

Buone pratiche

4.1. Favorire la composizione rispetto all’ereditarietà

Ereditarietà e composizione, entrambi i tipi di promuovere la riusabilità del codice. Ma l’uso della composizione è preferito rispetto all’ereditarietà.,

Un’implementazione della composizione sull’ereditarietà inizia in genere con la creazione di varie interfacce che rappresentano i comportamenti che il sistema deve esibire. Le interfacce consentono un comportamento polimorfico. Le classi che implementano le interfacce identificate vengono create e aggiunte alle classi di dominio aziendale secondo necessità. Pertanto, i comportamenti di sistema sono realizzati senza ereditarietà.

4.2. Programma per un’interfaccia, non per l’implementazione

Questo porta a codice flessibile che può funzionare con qualsiasi nuova implementazione dell’interfaccia., Dovremmo mirare a utilizzare le interfacce come variabili, come tipi di ritorno di un metodo o come tipo di argomento di metodi.

Le interfacce agiscono come tipi di superclasse. In questo modo, possiamo creare più specializzazioni dell’interfaccia in futuro senza modificare il codice esistente.

4.3. DRY (non ripetere te stesso)

Non scrivere codice duplicato, invece usa l’astrazione per astrarre le cose comuni in un unico posto.

Come regola generale, se si scrive lo stesso pezzo di codice in due punti, considerare l’estrazione in una funzione separata e chiamare la funzione in entrambi i punti.

4.4., Incapsulare ciò che cambia

Tutto il software ottiene modifiche nel tempo. Quindi, incapsula il codice che ti aspetti o sospetti di essere cambiato in futuro.

In Java, utilizzareprivate metodi per nascondere tali implementazioni dai client in modo che quando si apporta una modifica, il client non sia costretto a apportare modifiche al suo codice.

L’uso di modelli di progettazione è anche raccomandato per ottenere l’incapsulamento. Ad esempio, factory design pattern incapsula il codice di creazione degli oggetti e offre la flessibilità di introdurre un nuovo tipo in un secondo momento senza alcun impatto sui client esistenti.

4.5., Principio di responsabilità singola

È uno dei solidi principi del design della classe OOP. Sottolinea che una classe dovrebbe avere una e una sola responsabilità.

In altre parole, dovremmo scrivere, cambiare e mantenere una classe per un solo scopo. Questo ci darà la flessibilità di apportare modifiche in futuro senza preoccuparci degli impatti dei cambiamenti per un’altra entità.

4.6. Principio aperto chiuso

Sottolinea che i componenti software dovrebbero essere aperti per l’estensione, ma chiusi per la modifica.,

Ciò significa che le nostre classi dovrebbero essere progettate in modo tale che ogni volta che altri sviluppatori vogliono cambiare il flusso di controllo in condizioni specifiche nell’applicazione, tutto ciò di cui hanno bisogno per estendere la nostra classe e sovrascrivere alcune funzioni e il gioco è fatto.

Se altri sviluppatori non sono in grado di progettare il comportamento desiderato a causa di vincoli posti dalla nostra classe, allora dovremmo riconsiderare la modifica della nostra classe.

Ci sono molti altri concetti e definizioni in tutto il paradigma OOPs che impareremo in altri tutorial.

Buon apprendimento !!

Questo post è stato utile?,

Fateci sapere se ti è piaciuto il post. E ‘ l’unico modo per migliorare.
No