Cerca nel sito:
ricerca
avanzata

Frasi Celebri...

... I pregiudizi che le persone hanno gli uni verso gli altri scompaiono quando poi gli uni conoscono gli altri.

da "Star Trek" 

Sondaggio:

In quale citt? vi piacerebbe vivere?

New York
Londra
Roma
Madrid
Parigi
Milano
Tokyo
Berlino
Altro

visualizza risultati


 

Reimpiego per composizione

Benche` non sia stato esplicitamente mostrato, non c'e` alcun limite alla complessita` di un membro dato di un oggetto; un attributo puo` avere sia tipo elementare che tipo definito dall'utente, in particolare un attributo puo` a sua volta essere un oggetto.


  class Lavoro {
    public:
      Lavoro(/* Parametri */);

      /* ... */

    private:
      /* ... */
  };

  class Lavoratore {
    public:
      Lavoratore(Lavoro* occupazione);
      /* ... */

    private:
      Lavoro* Occupazione;
      /* ... */
  };


L'esempio mostrato suggerisce un modo di reimpiegare codice gia` pronto quando si e` di fronte ad una relazione di tipo Has-a, in cui una entita` piu` piccola e` effettivamente parte di una piu` grossa. In questo caso il reimpiego e` servito per modellare una proprieta` della classe Lavoratore, ma sono possibili casi ancora piu` complessi:


  class Complex {
    public:
      Complex(float Real=0, float Immag=0);
      Complex operator+(Complex &);
      Complex operator-(Complex &);
      /* ... */

    private:
      float Re, Im;
  };

  class Matrix {
    public:
      Matrix();
      Matrix operator+(Matrix &);
      /* ... */

    private:
      Complex Data[10][10];
  };


In questo secondo esempio invece il reimpiego della classe Complex ci consente anche di definire le operazioni sulla classe Matrix in termini delle operazioni su Complex (un approccio matematicamente corretto).
Tuttavia la composizione puo` essere utilizzata anche per modellare una relazione di tipo Is-a, in cui invece una istanza di un certo tipo puo` essere vista anche come istanza di un tipo piu` "piccolo":


  class Person {
    public:
      Person(const char* name, unsigned age);
      void PrintName();
      /* ... */

    private:
      const char* Name;
      unsiggned int Age;
  };

  class Student {
    public:
      Student(const char  name, unsigned age,
              const unsigned code);
      void PrintName();
      /* ... */

    private:
      Person Self;
      const unsigned int IdCode;  // numero di matricola
      /* ... */
  };

  Student::Student(const char* name, unsigned age,
                   const unsigned code)
         : Self(name, age), IdCode(code) {}

  void Student::PrintName() {
    Self.PrintName();
  }

  /* ... */


In sostanza la composizione puo` essere utilizzata anche quando vogliamo semplicemente estendere le funzionalita` di una classe realizzata in precedenza (esistono tecnologie basate su questo approccio).

Esistono due tecniche di composizione:

  • Contenimento diretto;
  • Contenimento tramite puntatori.
Nel primo caso un oggetto viene effettivamente inglobato all'interno di un altro (come negli esempi visti), nel secondo invece l'oggetto contenitore in realta` contiene un puntatore. Le due tecniche offrono vantaggi e svantaggi differenti.
Nel caso del contenimento tramite puntatori:
  • L'uso di puntatori permette di modellare relazioni 1-n, altrimenti non modellabili se non stabilendo un valore massimo per n;
  • Non e` necessario conoscere il modo in cui va costruito una componente nel momento in cui l'oggetto che la contiene viene istanziato;
  • E` possibile che piu` oggetti contenitori condividano la stessa componente;
  • Il contenimento tramite puntatori puo` essere utilizzato insieme all'ereditarieta` e al polimorfismo per realizzare classi di oggetti che non sono completamente definiti fino al momento in cui il tutto (compreso le parti accessibili tramite puntatori) non e` totalmente costruito.
L'ultimo punto e` probabilmente il piu` difficile da capire e richiede la conoscenza del concetto di ereditarieta` che sara` esaminato in seguito. Sostanzialmente possiamo dire che poiche` il contenimento avviene tramite puntatori, in effetti non possiamo conoscere l'esatto tipo del componente, ma solo una sua interfaccia generica (classe base) costituita dai messaggi cui l'oggetto puntato sicuramente risponde. Questo rende il contenimento tramite puntatori piu` flessibile e potente (espressivo) del contenimento diretto, potendo realizzare oggetti il cui comportamento puo` cambiare dinamicamente nel corso dell'esecuzione del programma (con il contenimento diretto invece oltre all'interfaccia viene fissato anche il comportamento ovvero l'implementazione del componente). Pensate al caso di una classe che modelli un'auto: utilizzando un puntatore per accedere alla componente motore, se vogliamo testare il comportamento dell'auto con un nuovo motore non dobbiamo fare altro che fare in modo che il puntatore punti ad un nuovo motore. Con il contenimento diretto la struttura del motore (corrispondente ai membri privati della componente) sarebbe stata limitata e non avremmo potuto testare l'auto con un motore di nuova concezione (ad esempio uno a propulsione anzicche` a scoppio). Come vedremo invece il polimorfismo consente di superare tale limite. Tutto cio` sara` comunque piu` chiaro in seguito.
Consideriamo ora i principali vantaggi e svantaggi del contenimento diretto:
  • L'accesso ai componenti non deve passare tramite puntatori;
  • La struttura di una classe e` nota gia` in fase di compilazione, si conosce subito l'esatto tipo del componente e il compilatore puo` effettuare molte ottimizzazioni (e controlli) altrimenti impossibili (tipo espansione delle funzioni inline dei componenti);
  • Non e` necessario eseguire operazioni di allocazione e deallocazione per costruire le componenti, ma e` necessario conoscere il modo in cui costruirle gia` quando si istanzia (costruisce) l'oggetto contenitore.

Se da una parte queste caratteristice rendono il contenimento diretto meno flessibile ed espressivo di quello tramite puntatore e anche vero che lo rendono piu` efficente, non tanto perche` non e` necessario passare tramite i puntatori, ma quanto per gli ultimi due punti.

 

successivo
–«  INDICE  »–

 

 

 

 
Powered by paper&pencil (carta&matita ) - Copyright © 2001-2019 Cataldo Sasso