Afficher un message
Vieux 07/05/2008, 09h02   #7
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Gestion de l'assignation consanguine

On May 7, 2:02 am, Mickaël Wolff <mickael.wo...@laposte.net> wrote:
> 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é ?


C'est qu'une opération sur un objet n'en vaut pas la même
opération sur un autre, même si la « valeur » est la même.
L'exemple typique (mais bien simplifié), c'est un compte en
banque, et une valeur qu'on y vire ou prélève. Le compte a une
identité ; faire la virement sur une copie de l'objet, ou un
autre objet qui a par hazard la même valeur ne va pas. La valeur
qu'on y vire ou prélève, en revanche, n'a pas d'identité : 100
Euros, c'est 100 Euros, que ce soit une copie ou non.

(Dans la pratique, il arrive qu'on fasse les copies des objets
ayant une identité, dans la gestion des transactions, par
exemple. Mais chaque opération s'effectue quand même sur une
instance précise de l'objet. On ne copie ni n'affecte pas
librement, mais seulement dans une contexte bien définie -- où
il serait bien acceptable, voire préférable, de faire
l'affectation ou la copie au moyen d'une fonction explicite,
plutôt que de se servir de l'opérateur.)

> > 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.


Les comparaisons ne présentent pas forcément tous les problèmes
des affectations. Si on suppose que le type dynamique fasse
partie de la « valeur », == renvoie faux dès que les types
sont différents (ce qui peut se faire simplement avec typeid).
Tandis que l'affectation n'est tout bonnement impossible entre
des types (dynamiques) différents.

> > (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é ?


Liskov Substitution Principle. En fait, oui, c'est un peu
l'interchangeabilité -- on doit pouvoir utiliser un Derived
partout ou un Base est démandé.

En fait, c'est lié à la notion du contrat : la base définit un
contrat, et tout dérivée doit le respecter. Et la
substitutabilité ne vaut, évidemment, que dans le cas où le
client respecte sa partie du contrat. (On peut, par exemple,
imaginer le cas où le code client ne marche qu'à cause des aléas
de l'implémentation de la base, et non à cause de quelque chose
de garantie par la base.) En gros, la dérivée ne doit pas
imposer des préconditions plus contraignantes, et doit garantir
des postconditions au moins aussi fortes que la base. Or, dans
ce que tu proposes, l'affectation d'une dérivée a la
précondition que ce qu'on affecte ait le type dérivée, et non
simplement base.

Mais comme d'habitude, ce n'est pas toujours aussi simple. Le
contrat peut être que l'affectation n'est admise que si
certaines conditions sont rempli. (Dans la bibliothèque
standard, par exemple, le contrat d'affectation d'un itérateur
exige que l'itérateur à droit de l'affectation n'ait pas une
valeur singulaire, c-à-d qu'il ne soit pas construit par le
constructeur par défaut.) Mais personnellement, je n'aime pas
trop que l'opérateur d'affectation ait des préconditions ; dans
de tels cas, je préfère de loin l'utilisation d'une fonction
nommée.

> > 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.


Ce qui suggère (à moi, et sans connaître toutes les contraintes)
l'interdiction de l'affectation dans la classe de base, avec son
implémentation éventuellement dans les classes dérivées.

Un autre alternatif serait de traiter le message comme si
c'était un espèce d'entité, même s'il n'en est pas une
logiquement, et de n'en copier que les pointeurs. (Puisque
logiquement, un message ne contiendrait pas d'autres pointeurs,
et donc, des cycles sont par définition impossible, on pourrait
très bien se servir de boost::shared_ptr dans ce cas pour glaner
les cellules, si on n'a pas d'autre glaneur de cellules.) A
priori, j'imagine qu'un message, une fois initialisé, est
immutable ; qu'on transmet des copies (valeur) ou des pointeurs
(identité) ne change donc strictement rien, en dehors des
questions de la gestion de la mémoire.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
  Réponse avec citation
 
Page generated in 0,07741 seconds with 9 queries