Vai alla Home Page About me Courseware Federica Living Library Federica Federica Podstudio Virtual Campus 3D Le Miniguide all'orientamento Gli eBook di Federica La Corte in Rete
 
I corsi di Ingegneria
 
Il Corso Le lezioni del Corso La Cattedra
 
Materiali di approfondimento Risorse Web Il Podcast di questa lezione

Stefano Russo » 6.Regole di traduzione da UML a Java/C++


Gap UML – C++/Java

Le specifiche UML sono indipendenti dal linguaggio di implementazione che sarà scelto in fase di codifica.

Per effettuare la corrispondenza dalle specifiche UML ad un linguaggio OO occorre pertanto colmare il gap, in termini di formalismi, esistente tra UML ed il linguaggio.

In relazione ai linguaggi C++ e Java il gap è colmato risolvendo:

  • la traduzione dei tipi degli attributi, dei parametri formali e di ritorno dei metodi;
  • le regole di ridefinibilità dei metodi (nelle strutture gen-spec);
  • la modalità di scambio dei parametri formali dei metodi.

Gap UML – C++

In molti casi la risoluzione del gap è affidata al codificatore cosicchè il progettista del sistema non si preoccupa di inserire ulteriori indicazioni nei diagrammi di progettazione.

Qualora il progettista ritenga utile limitare le scelte del codificatore può utilizzare, oltre che specifiche testuali “attaccate” agli elementi di progetto, il formalismo delle stringhe di proprietà {property-string} messe a disposizione da UML.

Mapping per le classi: attributi

Gli attributi in UML sono caratterizzati da: visibilità tipo_attributo nome_attributo, valore di default.

Regole per la traduzione

Gli attributi si mappano nelle variabili membro delle classi.

  • La visibilità è tradotta attraverso i qualificatori di accesso private, public, protected.
  • Se l’attributo è proprio della classe esso sarà di tipo static.
  • Se il tipo dell’attributo è una classe.
    • In C++ … può essere tradotto con una variabile membro di tipo classe o puntatore alla classe.
    • In Java … in un riferimento alla classe.
  • L’inizializzazione ai valori predefiniti degli attributi è effettuata tramite il costruttore della classe.

Mapping per le classi: metodi

I metodi UML sono caratterizzate da:

  • visibilità_funzione nome_funzione (lista dei parametri) : Tipo_ritorno

Le regole di traduzione per la visibilità sono le stesse di quelle per gli attributi.

La lista dei parametri contiene le coppie Tipo-Nome per i parametri di scambio.

  • E’ possibile specificare anche dei valori di default.
  • Non è direttamente specificabile, nella lista dei parametri, la direzione dei parametri di scambio (in, out, inout).

Mapping per le classi: metodi

Per la traduzione in C++, valgono le seguenti “regole”:

  • a metodi UML corrispondono funzioni membro;
  • la visibilità è automaticamente tradotta attraverso i qualificatori di accesso private, public, protected;
  • i metodi virtuali puri (VP) si traducono in funzioni membro virtuali pure;
  • in una gerarchia, i metodi che sono definiti nella classe base e ridefiniti in una classe derivata si traducono in funzioni membro virtuali (per la sovrapposizione);
  • i metodi della classe si traducono in funzioni membro di tipo static

Mapping per le classi: metodi

Per la traduzione in Java valgono le seguenti “regole”:

  • a metodi UML corrispondono funzioni membro;
  • la visibilità è automaticamente tradotta attraverso i qualificatori di accesso private, public, protected;
  • i metodi virtuali puri (VP) si traducono in funzioni membro abstract (metodi astratti);
  • … in java non ci sono problemi per la sovrapposizione dei metodi in una gerarchia;
  • i metodi della classe si traducono in funzioni membro di tipo static.

Parametri formali in C++

Per tradurre i parametri formali occorre tener conto del ruolo semantico dei parametri.

In base ad essi si applicano le “regole” generali del C++:

  • per i parametri di input semplici, si usa lo scambio per valore;
  • per i parametri di input complessi si usa lo scambio per riferimento (con il qualificatore const );
  • per i parametri di in-out o di out si usa lo scambio per riferimento;
  • per le funzioni che non alterano l’oggetto proprio si usa il qualificatore const dopo la lista dei parametri formali.

Parametri formali in Java

Per tradurre i parametri formali occorre tener conto del ruolo semantico dei parametri.
In base ad essi si applicano le “regole” generali di Java:

  • Per i parametri di input semplici (tipi primitivi), Java usa per default lo scambi per valore.
  • Per i parametri di input complessi, in genere si utilizza il metodo clone(), per eseguire un copia locale dell’oggetto (purtroppo Java non permette di etichettare un parametro complesso come argomento di ingresso)
  • Per i parametri di in-out o di out semplici, si utilizzano le classi Wrapper (Integer, Character…) per le quali Java utilizza solamente lo scambio per riferimento.
  • Per i parametri di in-out o di out complesso Java utilizza di default lo scambio per riferimento.

Tipo di ritorno dei metodi

Se si restituisce (eventualmente modificato) uno dei parametri di scambio, esso verrà restituito per riferimento

  • eventualmente con il qualificatore const laddove il parametro formale corrispondente sia di tipo const.

Qualora la funzione costruisca un nuovo oggetto è opportuno restituirlo per valore (solo C++)

  • laddove il valore restituito sia di un tipo strutturato non definito in alcuna delle classi esistenti dovrà essere definita, ad hoc, una specifica classe per la restituzione del valore strutturato.

Sovrapponibilità dei metodi

Nelle gerarchie gen-spec, le classi derivate possono ridefinire i metodi definiti dalla classe base.

La ridefinizione dei metodi dipende da come sono specificati i metodi nella classe base:

  • {V} metodi virtuali
  • {VP} metodi virtuali puri
  • {NV} metodi non virtuali

Metodi virtuali puri {VP}

La classe base può definire dei metodi cui non corrisponde alcun comportamento (metodi VP).

L’uso di metodi virtuali puri vincola le classi derivate a presentare un’interfaccia che sia al più una estesione di quella della classe base.

Una classe base che definisce metodi VP è detta classe astratta: da essa non sarà possibile istanziare direttamente oggetti non essendo definito il comportamento per i metodi VP.

Metodi virtuali

Metodi virtuali {V}, definiti dalla classe base, permettono una redifinizione da parte delle classi derivate.

L’uso di tali metodi è reso necessario quando gli oggetti istanza delle derivate possono esibire un comportamento diverso rispetto gli oggetti della base.

Dal punto di vista concettuale si parla di polimorfismo: il comportamento degli oggetti in relazione al metodo considerato non è univoco (polimorfo) ma dipende dalla specializzazione dell’oggetto stesso.

Metodi non virtuali

Metodi non virtuali (NV) definiti dalla classe base sono metodi che, usualmente, non necessitano di redifinizione nelle classi derivate (solo C++).

Esempio

In tale classe sono specificati:

  • tipi concettuali semplici (Intero e Carattere);
  • inizializzazione degli attributi;
  • due funzioni membro che non devono alterare l’oggetto proprio (LeggiIntero e Leggicarattere).

Traduzione in C++

Mostra codice

L'inizializzazione è realizzata tramite costruttore di default.

L'implentazione del costruttore sarà del tipo C::C(int iI, char cI): c( cI ), i( iI ).

Le funzioni che non devono alterare l'oggetto proprio hanno il qualificatore const.


Traduzione in Java

Mostra codice

Esempio traduzione strutture GenSpec

Le strutture generalizzazione specializzazione si traducono in C++ e in Java tramite il meccanismo linguistico dell’ereditarietà.


Esempio traduzione strutture GenSpec

Gli attributi della classe Automobile sono, in questo esempio, di tipo “protected”.

In tal modo si permette la visibilità di tali attributi a tutti gli oggetti istanza delle classi derivate (in Java anche alle classi appartenenti allo stesso package).

I metodi non sono ridefiniti nelle classi derivate.

  • In C++ essi possono essere tradotti in funzioni membro non virtuali.

Il tipo di derivazione (public) è stato specificato tramite una {stringa di proprietà}.

class Automobile

Mostra codice

class Fuoristrada in C++

Mostra codice

L'ereditarietà è pubblica

class Fuoristrada : public Automobile 

Metodi aggiuntivi
void Inserisci_Trazione_Integrale();

Attributo aggiuntivo

Kg Peso_massimo_rimorchio;

class Fuoristrada in Java

Mostra codice

In Java non è possibile specificare le modalità di derivazione. E' possibile impostare dei meccanismi di visibilità sulla classe base: pubblica (derivabile ed utilizzabile anche al di fuori) o non specificata (derivabile ed utilizzabile solo all'interno del package nel quale è stata definita. Se non definisco un package, Java ne utilizza uno di default).

Esempio di gen spec con ridefinizione di metodi nelle classi derivate.


Esempio di gen spec con ridefinizione di metodi nelle classi derivate

Quali sono le modifiche rispetto al caso precedente?

In Java…nessuna

In C++…

  • specificare il metodo Avvia() della classe Base di tipo virtual;
  • inserire la “signature” del metodo Avvia() anche nella definizione della derivata;
  • implementare tale metodo nell’implementazione della classe Fuoristrada.

Aggregazione


Aggregazione in senso “lasco”

Comporta l’indipendenza del ciclo di vita dell’oggetto contenuto dall’oggetto contenitore.

L’oggetto contenuto potrà quindi esistere anche indipendentemente dal contenitore.

Il contenitore non ha responsabilità per la creazione e distruzione dell’oggetto contenuto.

Aggregazione in senso “lasco”

In C++ si traduce in due modi diversi:

  • il contenitore ha una variabile membro privata di tipo
    • puntatore ad un oggetto di tipo contenuto;
    • riferimento ad un oggetto di tipo contenuto;

Il contenitore dovrà definire un costruttore che riceva in input il puntatore ( o il riferimento) all’oggetto contenuto.
In Java:

  • il contenitore ha una variabile membro privata di tipo riferimento ad un oggetto di tipo contenuto;
  • Il contenitore dovrà definire un costruttore che riceva in input il riferimento all’oggetto contenuto.

Esempio C++ 1 :Traduzione aggregazione “lasca” tramite puntatore

Mostra codice

Uso della classe C1

Mostra codice

Il main program ha la responsabilità di:

  • creare l'oggetto contenuto;
  • definire ed inizializzare un puntatore ad esso;
  • costruire l'oggetto contenitore passando il puntatore ad contenuto.

Esempio C++ 2 : Traduzione aggregazione “lasca” tramite riferimento

Mostra codice

Uso della classe C1

Il main program ha la responsabilità di:

  • creare l’oggetto contenuto.
  • definire ed inizializzare l’oggetto contenitore fornendo il riferimento del contenuto.
Mostra codice

Aggregazione in senso stretto

Indica che l’oggetto “contenuto” non ha una vita propria ma esiste in quanto parte dell’oggetto contenente.

L’oggetto “contenitore” è responsabile della costruzione e distruzione dell’oggetto contenuto.

Aggregazione in senso stretto

In C++, per tradurre tale relazione si dovrà:

  • aggiungere una variabile membro alla classe “contenitore” del tipo della classe “contenuto”;
  • implementare il costruttore del “contenuto” in modo da richiamare il costruttore del “contenitore”.

In Java

  • Un riferimento alla classe “contenuto” che venga creata;
  • nel costruttore del “contenitore” oppure
  • prima del costruttore, nella classe “contenitore”, cioè nel momento in cui è definito.

Esempio C++: Traduzione aggregazione in senso stretto

Mostra codice

Uso della classe C3

Il main program ha l’unica responsabilità di creare l’oggetto contenitore fornendo valori di inizializzazione sia per esso che per il contenuto.

Mostra codice

Associazione in UML

E’ caratterizzata da:

  • un nome (opzionale) che esprime il legame semantico tra le classi associate;
  • il ruolo giocato dalle parti associate (opzionale);
  • la molteplicità dell’associazione (mandatory) che esprime la cardinalità delle connessioni tra gli oggetti:
    • uno a uno;
    • uno a molti;
    • molti a molti;
  • la direzionalità (bidirezionale di default) che indica chi ha la responsabilità di tenere traccia dell’associazione.

Associazione in C++

Le relazioni di associazione si traducono con una o più variabili membro di tipo puntatore alla classe associata (a seconda della molteplicità dell’associazione).

Ogni classe definisce

  • un costruttore che riceva un puntatore alla classe associata (connessione alla creazione);
  • una funzione membro la cui semantica sia “CollegaParter(ClassePartner* p): connessione post creazione.

Associazione Uno a Uno

Se è specificato solo il nome dell’associazione la variabile membro di tipo puntatore prende il nome dell’associazione stessa.

Se è specificato il ruolo della classe associata il nome della variabile membro sarà quello dell’associazione stessa.

Esempio di associazione


Esempio di associazione in Java

 


Uso dell’associazione

Il programma principale avrà la responsabilità della creazione e del collegamento dei due oggetti, ad esempio:

Mostra codice

Altro esempio


Class Automobile

Mostra codice

Class Persona

Mostra codice
  • Contenuti protetti da Creative Commons
  • Feed RSS
  • Condividi su FriendFeed
  • Condividi su Facebook
  • Segnala su Twitter
  • Condividi su LinkedIn
Progetto "Campus Virtuale" dell'Università degli Studi di Napoli Federico II, realizzato con il cofinanziamento dell'Unione europea. Asse V - Società dell'informazione - Obiettivo Operativo 5.1 e-Government ed e-Inclusion