User Tools

Site Tools


appunti3s:relazioni_tra_classi

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
appunti3s:relazioni_tra_classi [2019/01/12 00:57] profproappunti3s:relazioni_tra_classi [2020/06/08 22:20] (current) – external edit 127.0.0.1
Line 1: Line 1:
 +> torna al menù principale > [[appunti3s:linguaggio_c]]
 +
 +====== Relazioni ta classi ======
 +
 +La //relazione// stabilisce un legame tra le //classi//.
 +(mentre i legami tra gli //oggetti// questi legami sono implementati con i //collegamenti//)
 +
 +  * Ha il **vantaggio** di consentire un riutilizzo del codice delle classi.
 +  * Ha lo **svantaggio** di creare accoppiamento e dipendenza del codice delle classi.
 +
 +===== Tipologie =====
 +Esistono diversi tipi di relazioni tra classi. Ogni tipo può essere descritto dalle seguenti caratteristiche:
 +  - Ogni relazione possiede: un nome e (uno o più) versi di navigabilità
 +  - Ogni classe coinvolta in una relazione può avere: un ruolo e una molteplicità
 +
 +In questa tabella si utilizza la simbologia dello standard [[appunti3s:uml]]
 +
 +^ relazione ^ verbo ^ verbo ^ n.versi ^ implementazione ^ simbolo ^
 +| [[appunti3s:relazioni tra classi#composizione]] | //has a// | costituire |  2  |  nested classes  |  {{ :appunti3s:cpp-composizione.png?150 |immagine}}| 
 +| [[appunti3s:relazioni tra classi#aggregazione]] | //has a// | costituire |  1  |  oggetti membro  |  {{ :appunti3s:cpp-aggregazione.png?150 |immagine}}|
 +| [[appunti3s:relazioni tra classi#associazione]] | //uses a// | utilizzare |  1-2  |  ref./point. membro |  {{ :appunti3s:cpp-associazione.png?150 |immagine}}|
 +| [[appunti3s:relazioni tra classi#dipendenza]]  | //uses a// | utilizzare |  1  |  ??  |  {{ :appunti3s:cpp-dipendenza.png?150 |immagine}}| 
 +| [[appunti3s:relazioni tra classi#generalizzazione]] | //is a// | essere |  1  |  [[appunti3s:ereditarietà1]]  |  {{ :appunti3s:cpp-generalizzazione.png?150 |immagine}}|
 +| [[appunti3s:relazioni tra classi#realizzazione]] | //is a// | essere |  1  |  [[appunti3s:polimorfismo]]  |  {{ :appunti3s:cpp-realizzazione.png?150 |immagine}}|
 +
 +Fare esempi e confronti di relazioni tra classi (fatte bene e fatte male)
 +
 +===== Traduzione =====
 +
 +Nel linguaggio C++ le relazioni tra classi possono essere tradotte usando diverse tecniche di programmazione orientata agli oggetti:
 +
 +  * una classe può essere definita dentro una classe (nested) (composizione)
 +  * una classe può essere definita fuori da una classe e instanziata dentro quella classe
 +    * come oggetto membro (aggregazione)
 +    * come puntatore o reference membro (associazione)
 +  * una classe può essere derivata a partire da un'altra classe (generalizzazione)
 +
 +In questa ampia scelta, sono da privilegiare le relazioni più deboli perché sono più semplici e creano una minore dipendenza tra i moduli. 
 +Quale tra quelle citate è la relazione più debole e quale quella più forte?
 +L'associazione? L'aggregazione? 
 +
 +
 +====== Composizione ======
 +{{:appunti3s:cpp-composizione.png|immagine}}
 +  * una linea continua con il simbolo del rombo pieno appoggiato alla classe //contenitore//
 +  * i numerini indicano la molteplicità
 +  * Ha sempre DUE versi di percorrenza (quindi due regole)
 +  * l'Aggregazione ha il simbolo del rombo vuoto. 
 +
 +===== Principio  di esclusività =====
 +  * La classe del componente può andar a comporre una sola classe contenitore
 +  * Non si possono creare nuovi oggetti senza creare prima il loro oggetto contenitore
 +===== Descrizione =====
 +
 +Il verbo usato per descrivere questa relazione è //has//: possedere, avere, essere composto da... 
 +Nella Composizione le classi componenti esistono solo in relazione alla classe contenitore. Non si possono creare oggetti al di fuori di tali classi.
 +
 +===== Come si realizza? =====
 +Poiché la relazione è forte è necessario dichiarare una classe nel namespace di una classe contenitore. 
 +In questo modo è realizzato anche il principio dell'esclusività.
 +<code>
 +Class A
 +{   
 + private:    
 +    Class B
 +    {
 +    };
 +};
 +</code>
 +
 +In questo modo tutte le funzioni membro della classe contenitore hanno accesso a tutti i dati membro dell'altra classe. Il costruttore della classe contenitore inizializzerà questi oggetti come inizializza gli altri oggetti. 
 +Se gli oggetti sono creati nello stack verranno inizializzati/distrutti automaticamente, mentre se puntato nell'heap **dovrà** occuparsene il costruttore/distruttore.
 +
 +Se è necessario usare più volte questi oggetti (come 4 gambe di un tavolo) si possono usare vector.
 +
 +Non confondere la molteplicità con il numero di versi di navigabilità.
 +<del>Se la molteplicità è uno si realizza aggiungendo dei puntatori nella classe //contenitore//.
 +Se la molteplicità è maggiore di uno si implementa con i vettori</del>
 +
 +===== Esempio =====
 +
 +Codice sorgente con esempio di {{:appunti3s:composizione.zip|composizione}}
 +
 +===== Esercizio =====
 +Creare le classi per disegnare punti e segmenti sul piano cartesiano.
 +Lo stesso esempio può essere risolto:
 +  * con l'aggregazione se considero i punti pre-esistenti al segmento e quindi indipendenti.
 +  * con la composizione se considero di creare due nuovi punti per ogni segmento (non rappresento punti singoli)
 +
 +
 +
 +
 +
 +====== Aggregazione ======
 +{{:appunti3s:cpp-aggregazione.png|immagine}}
 +  * una linea continua con il simbolo del rombo vuoto vicino alla classe //contenitore//
 +  * i numerini indicano la molteplicità 
 +  * Ha sempre UNO SOLO verso di percorrenza (quindi una regola)
 +  * la Composizione ha il simbolo del rombo pieno.
 +
 +===== Principio =====
 +Il verbo usato per descrivere questa relazione è //has//: possedere, avere, essere composto da... 
 +Nell'Aggregazione le classi componenti esistono indipendentemente dalla classe contenitore
 +
 +===== Come si realizza? =====
 +Possedere un oggetto significa avere un oggetto membro di quel tipo...
 +Le classi componenti esistono indipendentemente dalla classe contenitore, quindi __non__ è necessario definire tali classi all'interno dei contenitori, come lo è invece nella composizione. <del>, perciò il distruttore del contenitore **non** si deve occupare della distruzione delle componenti.</del> <del>Se la molteplicità è uno si realizza aggiungendo dei reference nella classe //contenitore//.
 +Se la molteplicità è maggiore di uno si implementa con array di puntatori o vector (i vector lavorano per copia)
 +</del>
 +<code>
 +class B
 +{
 + //...
 +};
 +
 +class A
 +{
 +   private:
 +        B m_b;
 +};
 +</code>
 +
 +
 +===== Esempio =====
 +File sorgenti di un esempio di {{:appunti3s:aggregazione.zip|aggregazione}}
 +
 +===== Esercizio =====
 +Creare le classi per disegnare punti e segmenti sul piano cartesiano.
 +Lo stesso esempio può essere risolto:
 +  * con l'aggregazione se considero i punti pre-esistenti al segmento e quindi indipendenti.
 +  * con la composizione se considero di creare due nuovi punti per ogni segmento (non rappresento punti singoli)
 +  * 
 +====Analisi del problema====
 +  - il segmento può essere creato a partire da punti pre-esistenti?
 +  - cosa accade al punto se distruggo il segmento?(esclusività)
 +  - cosa accade al segmento se distruggo un suo punto?
 +  - un punto può appartenere a due segmenti contemporaneamente?(esclusività)
 +
 +
 +
 +
 +====== Associazione ======
 +{{:appunti3s:cpp-associazione.png|immagine}}
 +  * La relazione di Associazione si rappresenta con una o due frecce su una linea continua.
 +  * L'Associazione ha un nome
 +  * I numerini indicano la molteplicità minima e massima (0..3, 1, *)
 +  * Le classi possono avere un ruolo
 +  * __Può avere due versi__ di navigabilità (una o due frecce sulla linea), cioè DUE regole
 +  * La relazione di Dipendenza si rappresenta con la freccia a linea tratteggiata. (classi astratte???)
 +===== Principio =====
 +Il verbo usato per descrivere questa relazione è //uses//: utilizzare 
 +
 +===== Come si realizza? =====
 +Se A e B sono in relazione di associazione, allora le funzioni membro della classe A usano (//usa//) oggetti di tipo B. Questo si può tradurre in:
 +  - avere funzioni che hanno come argomenti copie, puntatori o reference a oggetti di tipo B
 +  - avere funzioni che restituiscono copie, puntatori o reference a oggetti di tipo B.
 +  - avere membri di tipo reference o puntatori a oggetti di tipo B
 +<code>
 +Class B; // nell'interfaccia non serve la definizione completa di B...
 +
 +Class A
 +{
 +   public:
 +           void fun(B& b);
 +};
 +</code>
 +
 +A differenza della relazione di //aggregazione//, in quella di //associazione// il compilatore deve solo usare un indirizzo di memoria e nell'interfaccia della classe non deve conoscere necessariamente la dimensione dell'oggetto usato. 
 +Nel file sorgente che implementa la classe invece si deve conoscere anche la dimensione dell'oggetto usato...
 +
 +===== Esempio =====
 +Esempio di codice che fa uso dell'{{:appunti3s:associazione.zip|associazione}}
 +
 +
 +
 +===== Esercizio =====
 +====  molti a molti ====
 +Sviluppare due classi che rappresentino il concetto di auto e di persona, nel senso che: 
 +  * ogni persona possiede più auto
 +  * ogni auto appartiene a più persone
 +La presenza di DUE REGOLE indica un doppio orientamento: partendo da auto si può arrivare a persona e viceversa. <del> contraddizione con precedente paragrafo???come si realizza????quando e' a uno si usa un puntatore alla classe vicina ???quando e' a molti si usa un vettore di puntatori</del>
 +
 +Tra due classi ci possono essere anche più relazioni (ad esempio l'auto può "appartenere" ma si può anche "guidare"). Può esistere lassociazione riflessiva??
 +
 +Altro esempio molti a molti con i conti correnti e i correntisti... 
 +Il membro "saldo" è un dato "private" perché deve essere modificabile solo dalle funzioni membro del conto (come versamento o prelievo)
 +
 +=== Classi associative ===
 +
 +Se la relazione di associazione ha degli "attributi" si fa una linea tratteggiata perpendicolare a quella continua che rappresenta l'associazione e ci si attaccano gli attributi con una classe (detta appunto //classe associativa//) che ha lo stesso nome dell'associazione. Quella classe conterrà gli attributi dell'associazione. In realtà questo schema di due classi più una classe associativa, potrebbe essere realizzato in modo equivalente anche con tre classi "normali" e due associazioni (uno a molti?)
 +
 +==== Uno a molti ====
 +
 +  * ogni classe possiede uno o più studenti
 +  * ogni studente è contenuto in una classe
 +
 +
 +
 +====== Generalizzazione ======
 +{{:appunti3s:cpp-generalizzazione.png|immagine}}
 +  * è quasi la stessa cosa dell'[[appunti3s:ereditarietà1]], per approfondimento vedere libro "Usare UML"
 +  * ha il simbolo della linea continua che termina con un triangolo
 +  * ha UN SOLO verso e quindi una sola regola (vedi esempio)
 +
 +===== Principio di sostituzione =====
 +Un oggetto della classe derivata implementa sia il modello della classe base che della classe derivata.
 +
 +===== Come si realizza? =====
 +Si definisce la classe A come classe //derivata// dalla classe B , che è la classe //base//
 +<code>
 +Class B
 +{
 +  //etc.
 +};
 +
 +class A : public B
 +{
 +  //etc.
 +};
 +</code>
 +In questo modo la classe A avrà, oltre ai propri membri, anche quelli ereditati da B.
 +
 +Rispetto alla relazione di Aggregazione (o di Associazione), in questo caso, A può accedere ai membri dello stesso tipo di B senza aver bisogno di creare un oggetto di tipo B perché è lui stesso un oggetto di tipo B. 
 +
 +Questo può essere utile quando ...?
 +===== Esempio =====
 +{{:appunti3s:autoveicolo1.png|immagine}}
 +La relazione si riconosce quando nelle regole si può leggere: 
 +**Ogni oggetto-derivato è un (//is a//) oggetto-base** (non viceversa). 
 +Ogni automobile è un autoveicolo, Ogni camion è un autoveicolo, ecc...
 + 
 +
 +
 +
 +
 +====== Realizzazione ======
 +{{:appunti3s:cpp-realizzazione.png|immagine}}
 +
 +  * si rapprensenta con una linea tratteggiata che termina con un triangolo.
 +===== Descrizione =====
 +
 +Si tratta di un caso particolare della generalizzazione ([[appunti3s:ereditarietà]]) in cui la classe base è una //classe astratta// (contiene cioè almeno una funzione membro virtuale pura).
 +
 +Le classi astratte non vengono usate per instanziare oggetti ma per progettare un metodo di generazione del codice...
 +
 +===== Esempio =====
 +
 +vedi esempio [[appunti3s:relazioni tra classi#generalizzazione]]
 +
 +in realtà non esistono oggetti autoveicoli che hanno una targa, un proprietario, ecc. Quindi questa classe è presente solo per poter creare più facilmente nuove classi come auto e camion. Per le regole di invocazione dei metodi vedere [[appunti3s:polimorfismo]]