Newsgroup: it.comp.lang.c++
Titolo: C++ : Metafora Container-Contained ( Object )

Esiste un buon design pattern che illustri questa metodologia ? l'idea e' 
quella di avere una classe astratta interfaccia che definisca le 
funzionalita' di un contenitore (niente template), cosi' come un'altra 
interfaccia Object, che e' anche l'oggetto contenuto, ovviamente le due 
interfacce devono essere parallelizzabili:
Class Cassetto: public iContainer,public iObject // contenuto da Armadio
{
}
Voi vi chiederete, qual'e il problema? beh, fino a che ci si limita alla 
struttura delle classi negli esempi non c'e nessun problema o dubbio, ma 
quando andiamo a stendere la lista delle member function definite dalle 
due interfacce...
ad esempio, ponendo un caso (con la specializzazione delle interfacce 
descritte sopra) iGUIContainer (Contenitore di elementi di interfaccia) e 
iGUIObject, quale dei due deve implementare il meccanismo di ri
.>

Mi sembra che il problema stia alla base: l'orientamento ad oggetti e'
poco adatto a rappresentare la relazione tra contenitore e contenuto,
perche' o pone troppi vincoli sulle caratteristiche del contenitore
(ovvero contenitore omogeneo di oggetti molto specifici) o ne pone
troppo pochi sul contenuto (contenitore di oggetti derivati da una
classe base comune).
Tra l'altro il discorso e' molto difficile da generalizzare: al livello
piu' generico possibile un contenitore non pone vincoli sul contenuto,
salvo che sia istanziabile o copiabile, concetti difficili da
rappresentare in una classe base. Se invece il contenitore e' intrusivo,
ad esempio una lista i cui componenti devono gestire il puntatore
all'elemento successivo, devi imporre l'eredita' da una classe
"ElementoDiLista" che ha poco a che vedere con l'eventuale classe base
(vuota?) e quasi certamente niente a che vedere con l'effettivo scopo
della classe contenuta.
Scusa, ma mi pare che ti stai lanciando a studiare un problema teorico
che non solo non ha rilevanza pratica, ma che porta ad adoperare
soluzioni errate dal punto di vista del disegno. Piuttosto, se vuoi
occuparti di contenitori, studia i concetti che stanno alla base della
Standard Template Library.
Ciao,
Nicola

iGUIObject, quale dei due deve implementare il meccanismo di ri
????
Frase abortita?
Paolo
-----------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------

classe base comune).
Questa non la capisco... cosa intendi per orientamento ad oggetti?
Qualunque approccio tu segua o hai un contenitore di oggetti di
tipo ben preciso, oppure di oggetti appartenenti a certe categorie
(al limite tutte), le possibilita` sono ovviamente legate a cio` che
il linguaggio ti offre.


Il problema a mio avviso sta nel fatto di esprimere attraverso
l'ereditarieta' la relazione tra contenuto e contenitore. Posso avere:
class Pera {...};
class CestoDiPere {
  void aggiungi(Pera * p) {...}
  Pera * togli() {...}
};
oppure
class Contenibile {...}
class Pera : public Contenibile {...}
class CestoDiContenibili {
  void aggiungi(Contenibile * p) {...}
  Contenibile * togli() {...}
};
Nel primo caso ho il problema che per avere un cesto di mele devo
riscrivere tutto, nel secondo ho invece la perdita dell'informazione di
tipo nel passaggio attraverso il contenitore. Nota che una soluzione del
tipo implementare il primo usando il secondo riduce i problemi ma non li
risolve: devo comunque implementare CestoDiMele separatamente cosi' come
devo servirmi di un dynamic_cast in uscita, violando a mio avviso il
requisito originale che la relazione fosse espressa in termini di OO
pura.
Invece, se approccio il problema dal punto di vista della programmazione
generica, non esprimo esplicitamente nel codice i vincoli cui il
contenuto deve sottostare, ma in termini concettuali, ad esempio:
- dev'essere assegnabile
- dev'essere definito un'ordinamento totale
Con questa base posso scrivere i template corrispondenti, come:
template <class Contenibile> class Cesto {
  void aggiungi(Contenibile * c) {...}
  Contenibile * togli() {...}
};
Al proposito ho trovato molto interessante la parte introduttiva di
"Generic programming and the STL" di Matthew Austern (il resto del libro
devo ancora leggerlo...), o per quanto riguarda la riduttivita' di
considerare l'OO paradigma privilegiato nell'uso del C++ "Multiparadigm
design for C++" di James Coplien.
Ciao,
Nicola Musatti

>Standard Template Library.
Il problema e' che vorrei evitare la programmazione generica, di fatto 
con essa (e con il lavoro di Alex Stepanov) si risolvono quasi tutti i 
problemi da te citati, pero' usando dei template...
L'intrusivita' di un contenitore viene tenuta a bada dalla 
specializzazione dell'interfaccia base
-- 
universe::earth::internet::albion->Greetz++;
 
darX...@tin.it
 
alb...@libero.it
  Fido 2:335/234.21   
http://darxstar.cjb.net
  ICQ UIN# 11151997 - eggdrop on demand
<the trees that whisper in the evening...>

design for C++" di James Coplien.
Il paradigma ad oggetti del C++ non e` certo perfetto e soffre di alcuni
limiti (in primo luogo del fatto che i tipi primitivi non sono classi), 
in tal senso i template sono molto importanti. Tuttavia e` dimostrato
(B. Meyer "Genericity vs Inheritance", Proceeding of OOPSLA '86,
che purtroppo conosco solo indirettamente) che la programmazione
generica e` un sottoinsieme della OOP in un linguaggio ad oggetti
puro e con covarianza, tipo appunto eiffel. Per la cronaca eiffel dal
poco che ho visto offre i template, ma pare che il loro uso sia
estremamente limitato.


 puro e con covarianza, tipo appunto eiffel.
E se non ti scoccia mi spiegheresti anche cos'è la covarianza?
Grazie.
EMG

E se non ti scoccia mi spiegheresti anche cos'è la covarianza?
La covarianza e` una possibile regola per la ridefinizione dei metodi
di una classe derivata, l'altra possibilita` e` la controvarianza (nel
C++ viene utilizzata una versione "ridotta" della controvarianza).
Partiamo dalla controvarianza...
Nella controvarianza se ridefinisci un metodo di classe base i
suoi parametri devono essere dello stesso tipo di quelli nella
definizione della classe base, oppure di tipo derivato, il tipo
restituito invece puo` variare in senso contrario divenendo al piu` 
un supertipo di quello specificato nella definizione ereditata:
es.:
class TBaseA {};
class TDerivedA : public TBaseA {};
class TBaseB {};
class TDerivedB : public TBaseB {
  public:
    TBaseA* Foo(TDerivedA*);
};
class TDerived2B : public TDerivedB {
  public:
    TDerivedA* Foo(TBaseA*);
};
Cio` equivale a dire che il metodo di classe derivata deve accettare
almeno tutti i possibili valori validi per il metodo di classe base. Il 
valore restituito deve essere invece al piu` uno di quelli restituiti
dal metodo di classe base. La controvarianza permette di verificare
a compile time il principio di sostituibilita` ed e` utilizzata nei 
linguaggi con type checking statico (es C++)
La covarianza invece permette che il tipo restituito e quello dei
parametri varino nello stesso senso rimanendo dello stesso tipo
oppure assumendo un sottotipo.
es. (scritto in C++, na non valido in questo linguaggio):
class TBaseA {};
class TDerivedA : public TBaseA {};
class TBaseB {};
class TDerivedB : public TBaseB {
  public:
    TBaseA* Foo(TBaseA*);
};
class TDerived2B : public TDerivedB {
  public:
    TDerivedA* Foo(TDerivedA*);
};
La covarianza supera alcuni limiti della controvarianza, ma la
verifica del principio di sostituibilita` puo` essere fatto solo
utilizzando algoritmi di analisi data flow, oppure a tempo di esecuzione
(run time) utilizzando un type checking dinamico (e pagando quindi
un certo overhead).
Spero di essere stato sufficientemente chiaro (ho qualche dubbio)...


 Spero di essere stato sufficientemente chiaro (ho qualche dubbio)...
Grazie. Certo, l'argomento andrebbe approfondito...
EMG

E se non ti scoccia mi spiegheresti anche cos'è la covarianza?
 
E' una FAQ di eiffel: puoi trovarla a 
http://outback.eiffel.com/faq/language/co_contravar.html
-- 
God is Real, unless declared Integer.
ObjectZone - 
http://space.tin.it/computer/csadun/

>Frase abortita?
Ehm, mi spiace...ho avuto un leggero problemino :-((
riposto tutto in un nuovo thread facciamo prima...
