JavaRush /Java Blog /Random-IT /Concetti di programmazione orientata agli oggetti JAVA
shabnahm
Livello 18

Concetti di programmazione orientata agli oggetti JAVA

Pubblicato nel gruppo Random-IT
JAVA si basa sui concetti della programmazione orientata agli oggetti, che consente di passare a un livello di astrazione più elevato per risolvere qualsiasi problema in modo realistico. L'approccio orientato agli oggetti concettualizza la soluzione a un problema in termini di oggetti del mondo reale che sono più facili da riutilizzare in un'applicazione. Ad esempio, Chair(sedia), Fan(ventilatore), Dog(cane), Computer(computer) e così via. In JAVA, una classe è un layout, un modello o un prototipo che definisce il comportamento generale di un oggetto di un determinato tipo. Un'istanza è un'implementazione separata di una classe e tutte le istanze di una classe hanno le stesse proprietà, descritte nella definizione della classe. Ad esempio, puoi definire una classe denominata Casa con numero di stanze come attributo e creare istanze della classe come una casa con due stanze, una casa con tre stanze e così via. Concetti di programmazione orientata agli oggetti JAVA - 1Vantaggi: di seguito sono elencati alcuni vantaggi dello sviluppo di software orientato agli oggetti.
  • Costi di supporto software ridotti, principalmente grazie al fatto che viene eseguito in modo modulare.
  • Riutilizzo del codice migliorato attraverso funzionalità come l'ereditarietà, con conseguente sviluppo del software più rapido.
  • Maggiore affidabilità e flessibilità del codice.
  • Facilità di comprensione grazie alla simulazione del mondo reale.
  • Migliore astrazione a livello di oggetto.
  • Ridurre la complessità del passaggio da una fase di sviluppo all’altra.
Le caratteristiche principali dell’OOP sono quattro:
  • Incapsulamento
  • Eredità
  • Polimorfismo
  • Astrazione

Incapsulamento

L'incapsulamento agisce come un contratto per un oggetto su cosa dovrebbe nascondere e cosa dovrebbe aprire per l'accesso da parte di altri oggetti. In JAVA utilizziamo un modificatore di accesso privateper nascondere un metodo e limitare l'accesso a una variabile dal mondo esterno. JAVA dispone inoltre di vari modificatori di accesso: public, default, protected, private, che vengono utilizzati per limitare la visibilità a diversi livelli. Ma l’obiettivo finale è incapsulare quelle cose che non dovrebbero essere cambiate. L'approccio che funziona meglio è che una classe dovrebbe avere un solo motivo per cambiare e l'incapsulamento rende la progettazione di quell'"unico motivo" una realtà. L'approccio corretto all'incapsulamento è nascondere le cose che cambiano frequentemente per evitare di danneggiare altre classi. Vantaggi: di seguito sono riportati alcuni dei vantaggi dell'incapsulamento:
  • Possiamo proteggere lo stato interno di un oggetto nascondendone gli attributi.
  • Ciò migliora la modularità del codice perché impedisce agli oggetti di interagire in modi imprevisti.
  • Migliora l'usabilità del codice.
  • Ciò supporta il rapporto contrattuale di un'entità specifica.
  • L'incapsulamento semplifica la manutenzione del software.
  • Le modifiche al codice possono essere apportate indipendentemente l'una dall'altra.

Polimorfismo

Il polimorfismo nella programmazione è la capacità di fornire la stessa interfaccia per diversi moduli sottostanti (tipi di dati). Ciò significa che le classi con funzionalità diverse condividono la stessa interfaccia e possono essere chiamate dinamicamente passando parametri per riferimento. Un classico esempio è la classe Shape(forma) e tutte le classi che ereditano da essa: square(quadrato), circle(cerchio), dodecahedron(dodecaedro), irregular polygon(poligono irregolare), splat(blob), e così via. In questo esempio, ogni classe avrà il proprio metodo Draw()e il codice client potrà semplicemente fare:
Shape shape = new Shape();
Shape.area()per ottenere il comportamento corretto di qualsiasi forma Il bello del polimorfismo è che il codice, lavorando con classi diverse, non ha bisogno di sapere quale classe sta utilizzando, poiché funzionano tutte secondo lo stesso principio. Il processo utilizzato dai linguaggi di programmazione orientati agli oggetti per implementare il polimorfismo dinamico è chiamato associazione dinamica. Nota: il polimorfismo è la capacità di scegliere metodi più specifici da eseguire a seconda dell'oggetto. Il polimorfismo si verifica quando le classi astratte non sono coinvolte. Vantaggi:
  • Creazione di codice riutilizzabile. Cioè, una volta che una classe è stata creata, implementata e testata, può essere utilizzata liberamente senza preoccuparsi di cosa sia scritto esattamente al suo interno.
  • Ciò consente un codice più generico e liberamente accoppiato.
  • Il tempo di compilazione è ridotto, il che accelera lo sviluppo.
  • Collegamento dinamico.
  • La stessa interfaccia può essere utilizzata per creare metodi con implementazioni diverse.
  • L'intera implementazione può essere sostituita utilizzando le stesse firme del metodo.
Metodo che sovrascrive come parte del polimorfismo. Un override interagisce con due metodi: un metodo nella classe genitore e un metodo nella classe derivata. Questi metodi hanno lo stesso nome e firme. La sostituzione consente di eseguire la stessa operazione in modi diversi per diversi tipi di oggetti. Per esempio:
while(it.hasNext()) {
Shape s = (Shape) it.next();
totalArea += s.area(dim); //будет применен полиморфизм и вызван нужный метод для каждого an object.
}
Concetti di programmazione orientata agli oggetti JAVA - 2Overloading dei metodi o polimorfismo ad hoc o polimorfismo statico L'overloading interagisce con più metodi della stessa classe che hanno lo stesso nome ma hanno firme di metodo diverse. Il ricaricamento consente di descrivere la stessa operazione in modi diversi per dati diversi. A volte viene chiamato polimorfismo statico, ma in realtà non è polimorfismo. Questo non è altro che avere semplicemente due metodi con gli stessi nomi, ma un diverso elenco di argomenti. Il riavvio non ha nulla a che fare con l'ereditarietà e il polimorfismo. E un metodo sovraccaricato non è affatto la stessa cosa di un metodo sovrascritto. Polimorfismo parametrico tramite genericazione in JAVA Quando si dichiara una classe, il campo del nome può essere associato a tipi diversi e il nome del metodo può essere associato a parametri e tipi restituiti diversi. JAVA supporta il polimorfismo parametrico utilizzando i generici.
List<String> list = new ArrayList<String>();
Perché non possiamo sovrascrivere un metodo statico in JAVA? L'override dipende dall'esistenza di un'istanza della classe. L'idea del polimorfismo è che puoi creare una sottoclasse e gli oggetti implementati da quelle sottoclassi si comporteranno diversamente con gli stessi metodi della classe genitore (sovrascritti nelle sottoclassi). Un metodo statico non è associato ad alcuna istanza della classe, quindi il concetto di override stesso non può essere applicato. I creatori di JAVA sono stati guidati da due considerazioni che hanno influenzato questo approccio. Innanzitutto, ci sono problemi di esecuzione del codice: ci sono state molte critiche a Smalltalk per la sua lentezza (la raccolta dei rifiuti e il polimorfismo facevano parte di questo problema), e JAVA è stato progettato per evitarlo. La seconda considerazione è stata la decisione che il pubblico target di JAVA sarebbero stati gli sviluppatori C++. Il fatto che i metodi statici funzionassero in questo modo era molto familiare ai programmatori C++ e velocizzava anche le cose poiché non era necessario risalire la gerarchia delle classi per capire quale metodo chiamare. Vai direttamente alla classe e chiami un metodo specifico.

Eredità

L'ereditarietà è l'atto di incorporare il comportamento (ovvero i metodi) e lo stato (ovvero le variabili) di una classe base in una classe derivata in modo che diventino disponibili in quella classe derivata. Il vantaggio principale dell'ereditarietà è che fornisce un meccanismo formale per il riutilizzo del codice ed evita la duplicazione. Una classe ereditata estende la funzionalità dell'applicazione copiando il comportamento della classe genitore e aggiungendo nuove funzionalità. Ciò rende il codice altamente accoppiato. Se vuoi cambiare la superclasse, dovrai conoscere tutti i dettagli delle sottoclassi per non infrangere il codice. L'ereditarietà è una forma di riutilizzo del software in cui una nuova classe (sottoclasse) viene creata da una classe esistente (superclasse) che ne estende le funzionalità e utilizza alcune delle proprietà della superclasse. Quindi, se hai una classe genitore e poi appare una classe figlia, la classe figlia eredita tutte le cose che ha il genitore. Vantaggi:
  • Riutilizzo del codice migliorato.
  • Si stabilisce la relazione logica “è un” (è qualcuno, qualcosa). Ad esempio: il cane è un animale n . (Un cane è un animale).
  • Modularizzazione del codice.
  • Sono escluse le ripetizioni.
Difetto:
  • Strettamente accoppiato: una sottoclasse dipende dall'implementazione di una classe genitore, rendendo il codice strettamente accoppiato.

Astrazione

Astrazione significa progettare classi in base alle loro interfacce e funzionalità, senza tenere conto dei dettagli di implementazione. Una classe astratta rappresenta le interfacce senza includere l'implementazione effettiva. Distingue l'implementazione di un oggetto dal suo comportamento. L'astrazione semplifica il codice nascondendo dettagli non importanti. Vantaggi:
  • Usando l'astrazione, possiamo separare ciò che può essere raggruppato in qualche tipo.
  • Le proprietà e i metodi che cambiano frequentemente possono essere raggruppati in un tipo separato, in modo che il tipo principale non sia soggetto a modifiche. Ciò rafforza il principio OOP: “Il codice dovrebbe essere aperto all’estensione, ma chiuso al cambiamento ” .
  • L'astrazione semplifica la rappresentazione dei modelli di dominio.
Differenza tra astrazione e incapsulamento L'incapsulamento è una strategia utilizzata come parte dell'astrazione. L'incapsulamento si riferisce alla struttura di un oggetto: gli oggetti incapsulano le loro proprietà e le nascondono all'accesso esterno. Gli utenti di una classe interagiscono con essa utilizzando i suoi metodi, ma non hanno accesso diretto alla struttura della classe. In questo modo, la classe astrae i dettagli di implementazione relativi alla sua progettazione. Astrazione è un termine più generale. Ciò può essere ottenuto, tra le altre cose, anche utilizzando le sottoclassi. Ad esempio, una classe List(lista) nella libreria standard è un'astrazione per una sequenza di elementi, indicizzati in base alla loro posizione nella lista. Esempi specifici di elenco Listsono ArrayListo LinkedList. Il codice che interagisce con un elenco Listestrae i dettagli di quale elenco utilizza. Spesso l'astrazione non è possibile senza nascondere lo stato sottostante utilizzando l'incapsulamento. Se una classe espone la sua struttura interna, non può modificare le sue operazioni interne e quindi non può essere astratta. Cosa sono la classe astratta e il metodo astratto? Succede che durante lo sviluppo si desidera che una classe base fornisca solo un'interfaccia alle sue classi derivate. Cioè, non vuoi che nessuno crei istanze della classe base. È necessario utilizzare l'interfaccia in modo tale da eseguire il cast solo di oggetti (si tratta di un cast implicito che consente un comportamento polimorfico). Ciò si ottiene rendendo astratta questa classe utilizzando la parola chiave abstract. Ciò impone alcune restrizioni, come l'impossibilità di creare istanze di una classe astratta; quando si utilizza una classe astratta, è necessario implementare metodi astratti. Ciò garantisce il polimorfismo. Una classe astratta può contenere sia metodi astratti che concreti. Se almeno un metodo in una classe è dichiarato astratto, anche l'intera classe deve essere dichiarata astratta. Tuttavia non è necessario rispettare la regola contraria. Se una classe è dichiarata astratta, non può contenere metodi astratti. Un metodo che definisce semplicemente le proprie firme e non fornisce un'implementazione è chiamato astratto. La sua effettiva implementazione è lasciata alle sue sottoclassi, che estendono la classe astratta. Un metodo astratto non può essere utilizzato da un oggetto, solo un'altra classe può estenderlo. Quando dovresti usare una classe astratta? Le classi astratte consentono di definire alcuni comportamenti predefiniti e di fare in modo che le sottoclassi forniscano qualsiasi comportamento specifico. Ad esempio: List(list) è un'interfaccia, a sua volta AbstractListdefinisce il comportamento di base di un List, che può essere utilizzato così com'è o perfezionato in una sottoclasse, ad esempio in ArrayList(list array). Cos'è un'interfaccia? Il concetto di interfaccia è una classe astratta, ma l'interfaccia (definita dalla parola chiave interface) fa un ulteriore passo avanti. Impedisce qualsiasi implementazione di un metodo o di una funzione. Puoi solo dichiarare un metodo o una funzione, ma non fornirne l'implementazione. La classe che implementa l'interfaccia deve occuparsi dell'effettiva implementazione. Le interfacce sono molto utili e sono ampiamente utilizzate in OOP. Poiché condividono l'interfaccia stessa e l'implementazione, offrono molti vantaggi nel loro utilizzo:
  1. Eredità multipla .
  2. Accoppiamento lasco . Esiste un'astrazione dell'operazione, come la stratificazione, e l'implementazione concreta può essere qualsiasi cosa: JDBC, JPA, JTA, ecc.
  3. Il programma di interfaccia non è implementato .
  4. Polimorfismo di legame dinamico : l'interfaccia di programmazione di un oggetto viene esposta senza rivelarne l'effettiva implementazione.
  5. Livelli astratti , separazione delle funzionalità.
Differenza tra interfaccia e classe astratta.
  • Un'interfaccia è un rapporto contrattuale con le classi che implementano questa interfaccia, affermando che l'implementazione avviene nel modo indicato dall'interfaccia. Questa è una shell vuota con metodi dichiarati.
  • Una classe astratta definisce un comportamento generale e chiede alle sue sottoclassi di definire un comportamento atipico o specifico per la loro classe.
  • I metodi e i membri di una classe astratta possono essere designati con qualsiasi modificatore di accesso; a loro volta, tutti i metodi dell'interfaccia devono essere pubblici.
  • Quando si eredita una classe astratta, la classe discendente deve definire metodi astratti, mentre un'interfaccia può ereditare un'altra interfaccia senza necessariamente definirne i metodi.
  • Una classe discendente può estendere solo una classe astratta, ma un'interfaccia può estendere o una classe può implementare molte altre interfacce.
  • Una classe discendente può definire metodi astratti con lo stesso modificatore di accesso o meno restrittivo, ma la classe che implementa l'interfaccia deve definire metodi con lo stesso livello di visibilità.
  • Un'interfaccia non contiene costruttori, mentre una classe astratta sì.
  • Le variabili dichiarate nell'interfaccia Java sono definitive per impostazione predefinita. Una classe astratta può contenere variabili che non sono finali.
  • Tutti i membri dell'interfaccia Java sono public. I membri di una classe astratta possono permettersi di essere public, protectedecc.

Composizione

Il riutilizzo del codice può essere ottenuto utilizzando sia l'ereditarietà che la composizione. Ma l'utilizzo della composizione fornisce un livello di incapsulamento più elevato rispetto all'ereditarietà, poiché le modifiche alla classe back-end non influiranno necessariamente sul codice che appartiene alla classe front-end. La composizione è una tecnica di progettazione che utilizza le relazioni "ha-a" (ha, include) nelle classi. Sia l'ereditarietà Java che la composizione dell'oggetto possono essere utilizzate per riutilizzare il codice. L'essenza della composizione è esprimere la relazione "ha a" tra gli oggetti. Pensa a una sedia. La sedia ha un sedile. La sedia ha uno schienale. Una sedia ha un certo numero di gambe. La frase “ha a” suggerisce una relazione in cui la sedia ha, o almeno utilizza, un altro oggetto. Questa è proprio la relazione “has-a”, che è alla base della composizione. Vantaggi:
  • Controllo della visibilità
  • L'implementazione può essere sostituita in fase di esecuzione
  • Accoppiamento lento, poiché la classe dell'interfaccia non dipende dall'implementazione.
Differenze tra composizione ed ereditarietà
NO. Composizione (ha un / ha) Eredità (è un / è)
1 Supporta il polimorfismo e il riutilizzo del codice. Supporta il polimorfismo e il riutilizzo del codice.
2 L'oggetto runtime è già stato creato. L'oggetto viene creato dinamicamente in fase di compilazione.
3 L'implementazione può essere sostituita in fase di esecuzione. L'implementazione può essere modificata in fase di compilazione.
4 Una sottoclasse è indipendente dalla sua classe genitore, il che favorisce l'accoppiamento lento (specialmente sotto il controllo dell'interfaccia). La sottoclasse dipende dall'implementazione della classe genitore, quindi il legame è considerato forte.
5 Utilizzo: La casa dispone di un bagno. È sbagliato dire che la Casa è il Bagno. L'ereditarietà è unidirezionale: una Casa è un Edificio. Ma l'edificio non è una casa.
Nota: non utilizzare l'ereditarietà solo per garantire il riutilizzo del codice. Se non esiste la relazione “is a” (is), per questi scopi viene utilizzata la composizione. La differenza tra composizione e aggregazione sta nelle relazioni tra oggetti. L'aggregazione è una relazione in cui una classe si inserisce in una raccolta. È una parte di una relazione intera, dove una parte può esistere senza il tutto. Tali relazioni sono molto più deboli. Non esiste una dipendenza ciclica. Ad esempio: ordine e prodotto. La composizione è una relazione in cui una classe si inserisce in una raccolta. Questa è una parte di una relazione intera, in cui la parte non può esistere senza il tutto. Se il tutto viene distrutto, verranno distrutti anche tutti i suoi componenti. È una relazione più forte. Ad esempio: un poligono e i suoi vertici, un ordine e il suo componente.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION