CodeGym /Java Blog /Random-IT /Principi OOP
John Squirrels
Livello 41
San Francisco

Principi OOP

Pubblicato nel gruppo Random-IT
CIAO! Nella lezione di oggi parleremo dei Principi della programmazione orientata agli oggetti. Ti sei mai chiesto perché Java è progettato esattamente così com'è? Voglio dire, dichiari classi e crei oggetti basati su classi, le classi hanno metodi, ecc. Ma perché il linguaggio è strutturato in modo che i programmi siano costituiti da classi e oggetti e non qualcos'altro? Perché è stato inventato e messo in primo piano il concetto di "oggetto"? Tutte le lingue sono progettate in questo modo? In caso contrario, quali vantaggi offre a Java? Come puoi vedere, ci sono molte domande :) Proviamo a rispondere a ciascuna di esse nella lezione di oggi.

Cos'è la programmazione orientata agli oggetti (OOP)?

Ovviamente Java non è fatto di oggetti e classi solo per divertimento. Non sono un capriccio dei creatori di Java, e nemmeno una loro invenzione. Ci sono molti altri linguaggi basati su oggetti. Il primo tale linguaggio è stato chiamato "Simula". È stato inventato negli anni '60 in Norvegia. Inoltre, in Simula sono comparsi i concetti di "classe" e "metodo". Secondo gli standard di sviluppo del software, "Simula" sembra un linguaggio antico, ma chiunque può vedere la sua "somiglianza familiare" con Java. Principi di programmazione orientata agli oggetti - 1Probabilmente puoi facilmente leggere il codice scritto in questa lingua e spiegare a grandi linee cosa fa :)

Begin
	Class Rectangle (Width, Height); Real Width, Height;
			           
	 Begin
	    Real Area, Perimeter;  
	 
	    Procedure Update;      
	    Begin
	      Area := Width * Height;
              OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
	      Perimeter := 2*(Width + Height);
              OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
	    End of Update;
	 
	    Update;               
	    OutText("Rectangle created: "); OutFix(Width,2,6);
	    OutFix(Height,2,6); OutImage;
	 End of Rectangle;

       Rectangle Class ColouredRectangle (Color); Text Color;
			           
	Begin   	  
	    OutText("ColouredRectangle created, color = "); OutText(Color);
	    OutImage;
        End of ColouredRectangle;

 
      	 Ref(Rectangle) Cr;            
	 Cr :- New ColouredRectangle(10, 20, "Green"); 
End;
Questo codice di esempio è stato preso da "Simula - 50 anni di OOP" di Weekly-geekly. Come puoi vedere, Java non è molto diverso da suo nonno :) Questo è dovuto al fatto che la comparsa di Simula ha segnato la nascita di un nuovo concetto: la programmazione orientata agli oggetti. Wikipedia definisce OOP in questo modo: "La programmazione orientata agli oggetti (OOP) è un paradigma di programmazione basato sul concetto di "oggetti", che può contenere dati, sotto forma di campi (spesso noti come attributi), e codice, sotto forma di di procedure (spesso conosciute come metodi)." Secondo me, questa è davvero una buona definizione. Non è passato molto tempo da quando hai iniziato a imparare Java, ma questa definizione probabilmente non contiene parole che non conosci :) Oggi OOP è la metodologia di programmazione più comune. Oltre a Java, I principi OOP sono usati in molte lingue popolari di cui potresti aver sentito parlare. Ad esempio, C++ (utilizzato attivamente nello sviluppo di giochi), Objective-C e Swift (utilizzato per scrivere programmi per dispositivi Apple), Python (più popolare nell'apprendimento automatico), PHP (uno dei linguaggi di sviluppo web più popolari), JavaScript ( è più facile dire a cosa non serve) e molti altri. Quindi, quali sono comunque i principi dell'OOP? Ve lo raccontiamo nel dettaglio. quali sono i principi di OOP comunque? Ve lo raccontiamo nel dettaglio. quali sono i principi di OOP comunque? Ve lo raccontiamo nel dettaglio.

Principi OOP

Queste sono le fondamenta delle fondamenta. Le 4 caratteristiche principali che insieme formano il paradigma della programmazione orientata agli oggetti. Comprenderli è essenziale per diventare un programmatore di successo.

Principio 1. Ereditarietà

Buone notizie: conosci già alcuni dei principi di OOP! :) Abbiamo già incontrato l'ereditarietà un paio di volte durante le lezioni e siamo riusciti a usarla. L'ereditarietà è un meccanismo che consente di descrivere una nuova classe basata su una classe esistente (padre). In tal modo, la nuova classe prende in prestito le proprietà e le funzionalità della classe genitore. A cosa serve l'ereditarietà e quali vantaggi offre? Soprattutto, il riutilizzo del codice. I campi ei metodi dichiarati nelle classi padre possono essere utilizzati nelle classi discendenti. Se tutti i tipi di auto hanno 10 campi comuni e 5 metodi identici, devi solo spostarli in Autoclasse genitore. Puoi usarli nelle classi discendenti senza problemi. Solidi vantaggi: sia quantitativi (meno codice) che, di conseguenza, qualitativi (le classi diventano molto più semplici). Inoltre, l'ereditarietà è molto flessibile: puoi aggiungere funzionalità di scrittura separate che mancano ai discendenti (alcuni campi o comportamenti specifici di una particolare classe). In generale, come nella vita reale, siamo tutti in qualche modo simili ai nostri genitori, ma anche in qualche modo diversi da loro :)

Principio 2. Astrazione

Questo è un principio molto semplice. Astrazione significa identificare le caratteristiche principali e più significative di qualcosa, scartando contemporaneamente qualsiasi cosa minore e insignificante. Non c'è bisogno di reinventare la ruota. Ricordiamo un esempio da una vecchia lezione sulle lezioni. Supponiamo di creare un sistema di archiviazione per i dipendenti dell'azienda. Per creare oggetti "employee", abbiamo scritto una classe Employee . Quali caratteristiche sono importanti per descriverli nell'archivio aziendale? Nome, data di nascita, SSN e ID dipendente. Ma è improbabile che avremo bisogno dell'altezza, del colore degli occhi o dei capelli del dipendente per questo tipo di record. L'azienda non ha bisogno di tali informazioni su un dipendente. Quindi, nella classe Employee , dichiariamo le seguenti variabili:, int age , int socialSecurityNumber e int employeeId . E estraiamo informazioni non necessarie come il colore degli occhi. Tuttavia, se stiamo creando un sistema di archiviazione per un'agenzia di modelle, la situazione cambia radicalmente. L'altezza, il colore degli occhi e dei capelli di una modella sono caratteristiche importanti, ma il suo SSN è assolutamente irrilevante per noi. Quindi, nella classe Model , creiamo le seguenti variabili: String height , String hair , String eyes .

Principio 3. Incapsulamento

Ci siamo già imbattuti in questo. In Java, incapsulamento significa limitare la capacità di leggere e modificare i dati. Come puoi vedere, il termine si basa sulla parola "capsula". Useremo una "capsula" per nascondere alcuni dati importanti che non vogliamo che altri modifichino. Ecco un semplice esempio dalla vita reale. Hai un nome e un cognome. Tutti i tuoi amici li conoscono. Ma non hanno la possibilità di cambiare il tuo nome o cognome. Potremmo dire che il processo per farlo è "incapsulato" dal sistema giudiziario: puoi cambiare il tuo cognome solo attraverso il cancelliere, e solo tu puoi farlo. Altri "utenti" hanno accesso "in sola lettura" al tuo nome e cognome :) Un altro esempio illustrativo è il denaro contante tenuto in casa. Lasciarlo in bella vista nel mezzo della tua stanza non è una buona idea. Qualsiasi "utente" (persona che viene a casa tua) potrà cambiare l'importo dei tuoi soldi, cioè può prendere i tuoi soldi. Sarebbe meglio incapsularlo in una cassaforte. Quindi l'accesso sarebbe disponibile solo per te e solo utilizzando un codice speciale. Esempi evidenti di incapsulamento con cui hai già lavorato sono i modificatori di accesso (privati, pubblici, ecc.), nonché setter e getter. Se non incapsulare il fileCampo dell'età della classe del gatto , quindi chiunque può scrivere:

Cat.age = -1000;
Il meccanismo di incapsulamento ci consente di proteggere il campo dell'età con un metodo setter, in cui possiamo garantire che l'età non possa essere impostata su un numero negativo.

Principio 4. Polimorfismo

Il polimorfismo è la capacità di lavorare con diversi tipi come se fossero dello stesso tipo. Inoltre, il comportamento degli oggetti sarà diverso a seconda della loro tipologia. Sembra complicato? Diamogli un senso adesso. Prendi l'esempio più semplice: gli animali. Crea una classe Animal con un singolo metodo speak() e due sottoclassi: Cat e Dog .

public class Animal {

   public void speak() {
      
       System.out.println("Hello!");
   }
}

public class Dog extends Animal {
  
   @Override
   public void speak() {
       System.out.println ("Woof-woof!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}
Ora proveremo a dichiarare una variabile di riferimento Animal e ad assegnarle un oggetto Dog .

public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.speak();
   }
}
Quale metodo pensi che sarà chiamato? Animal.speak() o Dog.speak() ? Il metodo nella classe Cane si chiamerà: Bau-bau! Abbiamo creato un riferimento Animal , ma l'oggetto si comporta come un Dog . Se necessario, potrebbe comportarsi come un gatto, un cavallo o qualche altro animale. L'importante è assegnare una specifica sottoclasse alla variabile di riferimento generale Animale . Questo ha senso, perché tutti i cani sono animali. Questo è quello che avevamo in mente quando abbiamo detto "il comportamento degli oggetti sarà diverso a seconda del loro tipo". Se abbiamo creato un oggetto Gatto ...

public static void main(String[] args) {

   Animal cat = new Cat();
   cat.speak();
}
il metodo speak() visualizzerebbe "Meow!" Ma cosa intendiamo per 'la capacità di lavorare con diversi tipi come se fossero lo stesso tipo'? Anche questo è piuttosto semplice. Immaginiamo di creare un barbiere per animali. Il nostro barbiere dovrebbe essere in grado di rifinire qualsiasi animale, quindi creiamo un metodo trim() con un parametro Animal (l'animale che si taglia i capelli).

public class AnimalBarbershop {

   public void trim(Animal animal) {

       System.out.println("The haircut is done!"); 
   }
}
E ora possiamo passare gli oggetti Gatto e Cane al metodo trim() !

public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.trim(cat);
   barbershop.trim(dog);
}
Ed ecco il chiaro esempio: la classe AnimalBarbershop lavora con i tipi Gatto e Cane come se fossero dello stesso tipo. Allo stesso tempo, Gatto e Cane hanno comportamenti diversi: parlano ciascuno in modo diverso.

Perché abbiamo bisogno dell'OOP?

Perché l'OOP è mai nato come un nuovo concetto di programmazione? I programmatori avevano strumenti funzionanti, come i linguaggi procedurali. Cosa li ha spinti a inventare qualcosa di fondamentalmente nuovo? Soprattutto, la complessità dei compiti che hanno dovuto affrontare. Se 60 anni fa il compito del programmatore era qualcosa come "valutare qualche espressione matematica", ora potrebbe essere qualcosa come "implementare 7 diversi finali per il gioco STALKER, a seconda delle combinazioni delle decisioni del giocatore prese nei punti A, B, C, DE , e F nel gioco." Come puoi vedere, i compiti sono ovviamente diventati più complicati negli ultimi decenni. Di conseguenza, i tipi di dati sono diventati più complicati. Questo è un altro motivo per cui è apparso OOP. Un'espressione matematica può essere valutata facilmente usando primitive ordinarie. Non sono necessari oggetti qui. Ma il compito con i finali del gioco sarebbe difficile persino da descrivere senza utilizzare classi personalizzate. Detto questo, è abbastanza facile descriverlo usando classi e oggetti. Ovviamente, avremo bisogno di diverse classi: Game, Stalker, Ending, PlayerDecision, GameEvent e così via. In altre parole, anche senza iniziare a risolvere il problema, possiamo facilmente "abbozzare" una soluzione nella nostra testa. La crescente complessità dei compiti ha costretto i programmatori a dividerli in parti. Ma questo non era così facile da fare nella programmazione procedurale. E molto spesso un programma era come un albero con molti rami che rappresentavano tutti i possibili percorsi di esecuzione. A seconda di determinate condizioni, veniva eseguito un ramo del programma o un altro. Per i piccoli programmi, questo era conveniente, ma era molto difficile dividere un grosso problema in parti. Questa è stata un'altra ragione per l'emergere di OOP. Questo paradigma ha dato ai programmatori la possibilità di dividere un programma in una serie di "moduli" (classi), ognuno dei quali svolge la propria parte del lavoro. Interagendo tra loro, tutti gli oggetti compiono il lavoro del nostro programma. Inoltre, possiamo riutilizzare il nostro codice in altre parti del programma, risparmiando anche molto tempo.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION