James Kanze a écrit :
> Dans la pratique, tu dois te démander si ça a un sens. Au moins
> dans les applications que je fais, le polymorphisme s'applique
> surtout à des objets ayant une identité, et donc, qui ne
> supporte ni l'affectation ni la copie.
Qu'est-ce que tu appelles une identité ?
> class B0 : public A {
> {
> public:
> virtual B0& operator=( A const& other ) ;
> // ...
> } ;
Oui, en fait j'ai mal posé mes exemples. Finalement, dans le cas où
j'avais besoin d'affectations et de comparaisons virtuelles pour me
libérer de la nature des objets.
> (Que l'opérateur renvoie un B0& ou un A&, en revanche, n'a pas
> d'importance, puisque le C++ supporte les types de retour
> co-variants.)
Ça j'avais compris
> 1. On n'accepte l'affectation qu'entre des types dynamiques
> identiques. Mais dans ce cas-là, je me démande si on veut
> réelement l'affectation (ou la polymorphisme) ; pour
> certaines opérations (l'affectation), on n'est pas du tout
> polymorphique, et pour d'autres si. C'est en tout cas une
> violation flagrante du LSP.
LSP ~= interchangeabilité ?
> S'il le faudrait, j'interdirais l'affectation au niveau de
> la classe de base, et ne l'implémenterait qu'au niveau des
> classes dérivées. Si le client veut affecter, il faut qu'il
> sache avoir des instances de la même dérivée, et qu'il
> utilise leur interface. (Par exemple, qu'il ait fait un
> dynamic_cast avant, pour traiter un cas spécial.)
Ok.
> Dans la pratique, ce cas arrive facilement quand la classe
> de base représente une qualité plutôt indépendante du rôle
> de la classe, quelque chose comme PersistentObject. Dans ce
> cas-là, en revanche, on ne traite avec la classe de base que
> dans les fonctions qui gèrent cette qualité, ici par
> exemple, les fonctions d'entrée/sortie. Et l'affectation se
> fera bien toujours avec des classes dérivées.
C'est certainement ce qui m'arrive. Pour être concret, j'ai une classe
abstraite message. Cette classe fournit des services de base (canal
d'adressage du message), et enveloppe les données transmises. J'ai
essayé de penser à un système générique pour pouvoir les envoyer de la
vue au contrôleur et du modèle à la vue.
> 3. Enfin, on a réelement à faire avec une valeur polymorphique,
> dont le type dynamique fasse partie de la valeur, et doit
> être changé lors de l'affectation. Dans ce cas-ci, il faut
> l'idiome du lettre/enveloppe.
C'est marrant que tu parles d'enveloppe alors que j'envoie des messages.
> La détection, c'est le problème la plus simple :
>
> if ( typeid( *this ) != typeid( other ) ) ...
Certes.
> Je les évite, autant que possible. Dans la pratique, je trouve
> qu'ils apparaissent assez rarement, et quand ils apparaissent,
> ou bien, je me trouve dans le cas 1, ci-dessus, mais celui qui
> veut affecter sait toujours très bien le type (suite à un
> dynamic_cast au retour de la lecture, par exemple), et le
> problème ne se pose pas réelement, ou je me trouve dans le cas
> 3, mais avec des objets immutable, et je m'en tire en simplement
> affectant un pointeur (intelligent, genre boost::shared_ptr, si
> je n'ai pas de glaneur de cellules).
Merci pour toutes ces infos, ça m'a bien aidé à avancer. Même si je
suis de plus en plus convaincu d'avoir écrit une n-ième usine à gaz. :-/
Pas grave, je finirais par appliquer KISS ! Un jour.
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org