je voudrais votre avis sur une utilisation de l'héritage multiple qui ne
parait pas courante.
Soit une classe véhicule, dont l'utilisateur doit pouvoir déterminer la
position et à la couleur.
Soit une implémentation basée sur l'héritage multiple:
class Color {
public:
SetColor(...);
protected:
double r,g,b,a;
}
class Position {
public:
SetPosition(...);
protected:
double x,y;
}
class Vehicule : public Position, public Color {
...
}
Note: les classes Vehicule, Position, Color sont spécifiées et
implémentées par les mêmes développeurs (ie. pas d'héritage multiple de
classes "externes").
En gros, l'héritage multiple est utilisé pour ajouter en même temps une
interface et une implémentation à une classe.
Les avantages de cette implémentation sont les suivants:
- syntaxe très simple au niveau de Vehicule pour rajouter de nouvelles
propriétés
- très peu d'effort au niveau de Vehicule pour rajouter de nouvelles
propriétés
- Vehicule hérite automatiquement de toutes amélioration à Position
Par exemple, si SetPositionX() et SetPositionY() sont implémentées
dans Position(), Vehicule en profite automatiquement.
- syntaxe très simple pour l'utilisateur, qui n'a qu'à qu'à faire
monvehicule.SetColor()
Une limitation (au moins) est qu'on est embêté si le véhicule doit un
jour devenir bicolore.
A part ça, l'héritage multiple étant souvent sujet à controverse, y
a-t'il un risque particulier à une telle implémentation?
Quels sont les précautions à prendre?
On Sat, 12 Aug 2006 13:26:22 +0200, Olivier Croquette :
class Position { public: SetPosition(...); protected: double x,y; }
class Vehicule : public Position, public Color {
Je vois au moins trois problèmes :
1- Une position n'a pas de position.
Si tu écris Position ma_position; ma_position.SetPosition (...); tu écris "la position de la position ma_position est ...". Ça n'a pas de sens.
2- Ton héritage indique qu'un véhicule *est* une position. Là non plus, ça n'a pas de sens.
En fait, pour régler ces deux problèmes, il suffit de changer le nom de la classe, et de l'appeler "ObjetAyantUnePosition". On peut alors avoir une fonction "SetPosition" (un "objet ayant une position" a bien une position) ; et un "Véhicule" est bien un cas particulier d'objet ayant une position.
3- Des variables membres presque publiques, puisqu'une autre classe peut y accéder. Tôt ou tard, ça te causera des problèmes. D'une manière générale, toutes les variables membres doivent être privées.
On Sat, 12 Aug 2006 13:26:22 +0200, Olivier Croquette
<ocroquette@ocroquette.free.fr>:
class Position {
public:
SetPosition(...);
protected:
double x,y;
}
class Vehicule : public Position, public Color {
Je vois au moins trois problèmes :
1- Une position n'a pas de position.
Si tu écris
Position ma_position;
ma_position.SetPosition (...);
tu écris "la position de la position ma_position est ...".
Ça n'a pas de sens.
2- Ton héritage indique qu'un véhicule *est* une position.
Là non plus, ça n'a pas de sens.
En fait, pour régler ces deux problèmes, il suffit de changer le nom
de la classe, et de l'appeler "ObjetAyantUnePosition".
On peut alors avoir une fonction "SetPosition" (un
"objet ayant une position" a bien une position) ; et un "Véhicule" est
bien un cas particulier d'objet ayant une position.
3- Des variables membres presque publiques, puisqu'une autre classe
peut y accéder. Tôt ou tard, ça te causera des problèmes.
D'une manière générale, toutes les variables membres doivent être
privées.
On Sat, 12 Aug 2006 13:26:22 +0200, Olivier Croquette :
class Position { public: SetPosition(...); protected: double x,y; }
class Vehicule : public Position, public Color {
Je vois au moins trois problèmes :
1- Une position n'a pas de position.
Si tu écris Position ma_position; ma_position.SetPosition (...); tu écris "la position de la position ma_position est ...". Ça n'a pas de sens.
2- Ton héritage indique qu'un véhicule *est* une position. Là non plus, ça n'a pas de sens.
En fait, pour régler ces deux problèmes, il suffit de changer le nom de la classe, et de l'appeler "ObjetAyantUnePosition". On peut alors avoir une fonction "SetPosition" (un "objet ayant une position" a bien une position) ; et un "Véhicule" est bien un cas particulier d'objet ayant une position.
3- Des variables membres presque publiques, puisqu'une autre classe peut y accéder. Tôt ou tard, ça te causera des problèmes. D'une manière générale, toutes les variables membres doivent être privées.
Fabien LE LEZ
On Sat, 12 Aug 2006 13:26:22 +0200, Olivier Croquette :
class Position { public: SetPosition(...); protected: double x,y; }
J'oubliais les deux autres problèmes, qui sont sans doute des fautes de frappe : - il manque le point-virgule à la fin ; - il manque le destructeur virtuel.
On Sat, 12 Aug 2006 13:26:22 +0200, Olivier Croquette :
class Position {
public:
SetPosition(...);
protected:
double x,y;
}
J'oubliais les deux autres problèmes, qui sont sans doute des fautes
de frappe :
- il manque le point-virgule à la fin ;
- il manque le destructeur virtuel.
On Sat, 12 Aug 2006 13:26:22 +0200, Olivier Croquette :
class Position { public: SetPosition(...); protected: double x,y; }
J'oubliais les deux autres problèmes, qui sont sans doute des fautes de frappe : - il manque le point-virgule à la fin ; - il manque le destructeur virtuel.
Sylvain
Fabien LE LEZ wrote on 12/08/2006 13:37:
1- Une position n'a pas de position.
au primaire on apprend "être" et "avoir"; ici une position est un état.
Si tu écris Position ma_position; ma_position.SetPosition (...); tu écris "la position de la position ma_position est ...". Ça n'a pas de sens.
alors que dans "Position point;" 'point' a bien une position; voulais-tu seulement dire qu'il peut toujours exister une (mauvaise) façon de présenter qui permet de balayer le fond en raillant la forme ?
2- Ton héritage indique qu'un véhicule *est* une position. Là non plus, ça n'a pas de sens.
tu disais "a une position", tu te contredis juste pour contredire le PO? une véhicule a bien une position, non ?
En fait, pour régler ces deux problèmes, il suffit de changer le nom de la classe, et de l'appeler "ObjetAyantUnePosition".
ou encore "ClasseQuiPeutEtreEtenduParQuelqueChoseQuiPeutEtreOuAvoirUnePosition", mais bon c'est un peu long ...
3- Des variables membres presque publiques, puisqu'une autre classe peut y accéder. Tôt ou tard, ça te causera des problèmes. D'une manière générale, toutes les variables membres doivent être privées.
d'une manière générale, il faut se méfier des généralités ;)
Sylvain.
Fabien LE LEZ wrote on 12/08/2006 13:37:
1- Une position n'a pas de position.
au primaire on apprend "être" et "avoir"; ici une position est un état.
Si tu écris
Position ma_position;
ma_position.SetPosition (...);
tu écris "la position de la position ma_position est ...".
Ça n'a pas de sens.
alors que dans "Position point;" 'point' a bien une position; voulais-tu
seulement dire qu'il peut toujours exister une (mauvaise) façon de
présenter qui permet de balayer le fond en raillant la forme ?
2- Ton héritage indique qu'un véhicule *est* une position.
Là non plus, ça n'a pas de sens.
tu disais "a une position", tu te contredis juste pour contredire le PO?
une véhicule a bien une position, non ?
En fait, pour régler ces deux problèmes, il suffit de changer le nom
de la classe, et de l'appeler "ObjetAyantUnePosition".
ou encore
"ClasseQuiPeutEtreEtenduParQuelqueChoseQuiPeutEtreOuAvoirUnePosition",
mais bon c'est un peu long ...
3- Des variables membres presque publiques, puisqu'une autre classe
peut y accéder. Tôt ou tard, ça te causera des problèmes.
D'une manière générale, toutes les variables membres doivent être
privées.
d'une manière générale, il faut se méfier des généralités ;)
au primaire on apprend "être" et "avoir"; ici une position est un état.
Si tu écris Position ma_position; ma_position.SetPosition (...); tu écris "la position de la position ma_position est ...". Ça n'a pas de sens.
alors que dans "Position point;" 'point' a bien une position; voulais-tu seulement dire qu'il peut toujours exister une (mauvaise) façon de présenter qui permet de balayer le fond en raillant la forme ?
2- Ton héritage indique qu'un véhicule *est* une position. Là non plus, ça n'a pas de sens.
tu disais "a une position", tu te contredis juste pour contredire le PO? une véhicule a bien une position, non ?
En fait, pour régler ces deux problèmes, il suffit de changer le nom de la classe, et de l'appeler "ObjetAyantUnePosition".
ou encore "ClasseQuiPeutEtreEtenduParQuelqueChoseQuiPeutEtreOuAvoirUnePosition", mais bon c'est un peu long ...
3- Des variables membres presque publiques, puisqu'une autre classe peut y accéder. Tôt ou tard, ça te causera des problèmes. D'une manière générale, toutes les variables membres doivent être privées.
d'une manière générale, il faut se méfier des généralités ;)
Sylvain.
Alain Gaillard
A part ça, l'héritage multiple étant souvent sujet à controverse, y a-t'il un risque particulier à une telle implémentation? Quels sont les précautions à prendre?
AMHA il n'est pas ici question de controverse à propos d'héritage multiple. Normalement (comme l'a souligné Fabien), l'héritage exprime une relation "est-un". Comme par exemple une voiture de sport pourrais dériver d'une simple voiture. Une voiture n'est ni une position ni une couleur, mais a une position et a une couleur. La composition me semble beaucoup plus appropriée dans ce cas. Et du coup tu élimines les problèmes potentiels de l'héritage multiple :-)
-- Alain
A part ça, l'héritage multiple étant souvent sujet à controverse, y
a-t'il un risque particulier à une telle implémentation?
Quels sont les précautions à prendre?
AMHA il n'est pas ici question de controverse à propos d'héritage multiple.
Normalement (comme l'a souligné Fabien), l'héritage exprime une relation
"est-un". Comme par exemple une voiture de sport pourrais dériver d'une
simple voiture.
Une voiture n'est ni une position ni une couleur, mais a une position et
a une couleur. La composition me semble beaucoup plus appropriée dans ce
cas. Et du coup tu élimines les problèmes potentiels de l'héritage
multiple :-)
A part ça, l'héritage multiple étant souvent sujet à controverse, y a-t'il un risque particulier à une telle implémentation? Quels sont les précautions à prendre?
AMHA il n'est pas ici question de controverse à propos d'héritage multiple. Normalement (comme l'a souligné Fabien), l'héritage exprime une relation "est-un". Comme par exemple une voiture de sport pourrais dériver d'une simple voiture. Une voiture n'est ni une position ni une couleur, mais a une position et a une couleur. La composition me semble beaucoup plus appropriée dans ce cas. Et du coup tu élimines les problèmes potentiels de l'héritage multiple :-)
-- Alain
Alain Gaillard
A part ça, l'héritage multiple étant souvent sujet à controverse, y a-t'il un risque particulier à une telle implémentation? Quels sont les précautions à prendre?
AMHA il n'est pas ici question de controverse à propos d'héritage multiple. Normalement (comme l'a souligné Fabien), l'héritage exprime une relation "est-un". Comme par exemple une voiture de sport pourrait dériver d'une simple voiture. Une voiture n'est ni une position ni une couleur, mais a une position et a une couleur. La composition me semble beaucoup plus appropriée dans ce cas. Et du coup tu élimines les problèmes potentiels de l'héritage multiple :-)
-- Alain
A part ça, l'héritage multiple étant souvent sujet à controverse, y
a-t'il un risque particulier à une telle implémentation?
Quels sont les précautions à prendre?
AMHA il n'est pas ici question de controverse à propos d'héritage multiple.
Normalement (comme l'a souligné Fabien), l'héritage exprime une relation
"est-un". Comme par exemple une voiture de sport pourrait dériver d'une
simple voiture.
Une voiture n'est ni une position ni une couleur, mais a une position et
a une couleur. La composition me semble beaucoup plus appropriée dans ce
cas. Et du coup tu élimines les problèmes potentiels de l'héritage
multiple :-)
A part ça, l'héritage multiple étant souvent sujet à controverse, y a-t'il un risque particulier à une telle implémentation? Quels sont les précautions à prendre?
AMHA il n'est pas ici question de controverse à propos d'héritage multiple. Normalement (comme l'a souligné Fabien), l'héritage exprime une relation "est-un". Comme par exemple une voiture de sport pourrait dériver d'une simple voiture. Une voiture n'est ni une position ni une couleur, mais a une position et a une couleur. La composition me semble beaucoup plus appropriée dans ce cas. Et du coup tu élimines les problèmes potentiels de l'héritage multiple :-)
-- Alain
Arnaud Debaene
"Olivier Croquette" a écrit dans le message de news: ebkdsv$2k5$00$
Bonjour,
je voudrais votre avis sur une utilisation de l'héritage multiple qui ne parait pas courante.
Soit une classe véhicule, dont l'utilisateur doit pouvoir déterminer la position et à la couleur.
Soit une implémentation basée sur l'héritage multiple:
class Color { public: SetColor(...); protected: double r,g,b,a; }
class Position { public: SetPosition(...); protected: double x,y; }
class Vehicule : public Position, public Color { ... }
Lors d'une conception objet, il est toujours bon de se rappeler du principe de substitution de Liskov (LSP) : Il ne faut utiliser l'héritage publique que lorsque un objet dérivé "est" également un objet de la classe de base, et peut prendre sa place dans tous les usages que l'on peut faire de la classe de base.
Dans ton cas, tu est en train de dire : - qu'une voiture EST une couleur. Donc notamment et au hasard, qu'on peut "additionner" ou "soustraire" 2 voitures pour faire des mélanges chromatiques. - qu'une voiture EST une position. D'une part, cela sous-entend que Position est une classe mutable (qui peut changer dans le temps - sinon la voiture est immobilisée), mais pourquoi pas... Ensuite, une paire de voiture forment un vecteur spatial....
Mes exemples sont tirés par les cheveux, mais c'est pour te faire sentir ce que l'on entend généralement par héritage publique, et pourquoi ce n'est pas adapté dans to cas. La sur-utilisation de l'héritage est une erreur courante, et entraine toujours des problèmes de maintenabilité et d'évolutivité à long terme.
Au passage, dans les langages qui n'implémentent pas l'héritage multiple (C#, Java, etc...), un argument souvent avancé pour justifier leur choix est d'empêcher les programmeurs de faire ce genre de mauvais usage de l'héritage multiple et les "forcer" à faire le bon choix, celui de la composition.
Arnaud
"Olivier Croquette" <ocroquette@ocroquette.free.fr> a écrit dans le message
de news: ebkdsv$2k5$00$1@news.t-online.com...
Bonjour,
je voudrais votre avis sur une utilisation de l'héritage multiple qui ne
parait pas courante.
Soit une classe véhicule, dont l'utilisateur doit pouvoir déterminer la
position et à la couleur.
Soit une implémentation basée sur l'héritage multiple:
class Color {
public:
SetColor(...);
protected:
double r,g,b,a;
}
class Position {
public:
SetPosition(...);
protected:
double x,y;
}
class Vehicule : public Position, public Color {
...
}
Lors d'une conception objet, il est toujours bon de se rappeler du principe
de substitution de Liskov (LSP) : Il ne faut utiliser l'héritage publique
que lorsque un objet dérivé "est" également un objet de la classe de base,
et peut prendre sa place dans tous les usages que l'on peut faire de la
classe de base.
Dans ton cas, tu est en train de dire :
- qu'une voiture EST une couleur. Donc notamment et au hasard, qu'on peut
"additionner" ou "soustraire" 2 voitures pour faire des mélanges
chromatiques.
- qu'une voiture EST une position. D'une part, cela sous-entend que Position
est une classe mutable (qui peut changer dans le temps - sinon la voiture
est immobilisée), mais pourquoi pas... Ensuite, une paire de voiture forment
un vecteur spatial....
Mes exemples sont tirés par les cheveux, mais c'est pour te faire sentir ce
que l'on entend généralement par héritage publique, et pourquoi ce n'est pas
adapté dans to cas. La sur-utilisation de l'héritage est une erreur
courante, et entraine toujours des problèmes de maintenabilité et
d'évolutivité à long terme.
Au passage, dans les langages qui n'implémentent pas l'héritage multiple
(C#, Java, etc...), un argument souvent avancé pour justifier leur choix est
d'empêcher les programmeurs de faire ce genre de mauvais usage de l'héritage
multiple et les "forcer" à faire le bon choix, celui de la composition.
"Olivier Croquette" a écrit dans le message de news: ebkdsv$2k5$00$
Bonjour,
je voudrais votre avis sur une utilisation de l'héritage multiple qui ne parait pas courante.
Soit une classe véhicule, dont l'utilisateur doit pouvoir déterminer la position et à la couleur.
Soit une implémentation basée sur l'héritage multiple:
class Color { public: SetColor(...); protected: double r,g,b,a; }
class Position { public: SetPosition(...); protected: double x,y; }
class Vehicule : public Position, public Color { ... }
Lors d'une conception objet, il est toujours bon de se rappeler du principe de substitution de Liskov (LSP) : Il ne faut utiliser l'héritage publique que lorsque un objet dérivé "est" également un objet de la classe de base, et peut prendre sa place dans tous les usages que l'on peut faire de la classe de base.
Dans ton cas, tu est en train de dire : - qu'une voiture EST une couleur. Donc notamment et au hasard, qu'on peut "additionner" ou "soustraire" 2 voitures pour faire des mélanges chromatiques. - qu'une voiture EST une position. D'une part, cela sous-entend que Position est une classe mutable (qui peut changer dans le temps - sinon la voiture est immobilisée), mais pourquoi pas... Ensuite, une paire de voiture forment un vecteur spatial....
Mes exemples sont tirés par les cheveux, mais c'est pour te faire sentir ce que l'on entend généralement par héritage publique, et pourquoi ce n'est pas adapté dans to cas. La sur-utilisation de l'héritage est une erreur courante, et entraine toujours des problèmes de maintenabilité et d'évolutivité à long terme.
Au passage, dans les langages qui n'implémentent pas l'héritage multiple (C#, Java, etc...), un argument souvent avancé pour justifier leur choix est d'empêcher les programmeurs de faire ce genre de mauvais usage de l'héritage multiple et les "forcer" à faire le bon choix, celui de la composition.
Arnaud
Olivier Croquette
Merci pour vos commentaires!
Je me doutais bien que beaucoup déconseilleraient ce design, mais jusqu'à maintenant, je n'ai pas encore vu de description des problèmes *précis* auxquels cela expose.
De mon côté, j'y vois le gros avantage de simplifier énormément les écritures et de limiter la quantité de code trivial, genre:
Position &Vehicule::GetPositionRef() { return this->position; }
et ce pour chaque attribut.
Merci pour vos commentaires!
Je me doutais bien que beaucoup déconseilleraient ce design, mais
jusqu'à maintenant, je n'ai pas encore vu de description des problèmes
*précis* auxquels cela expose.
De mon côté, j'y vois le gros avantage de simplifier énormément les
écritures et de limiter la quantité de code trivial, genre:
Je me doutais bien que beaucoup déconseilleraient ce design, mais jusqu'à maintenant, je n'ai pas encore vu de description des problèmes *précis* auxquels cela expose.
De mon côté, j'y vois le gros avantage de simplifier énormément les écritures et de limiter la quantité de code trivial, genre:
Position &Vehicule::GetPositionRef() { return this->position; }
et ce pour chaque attribut.
Cyrille
Merci pour vos commentaires!
Je me doutais bien que beaucoup déconseilleraient ce design, mais jusqu'à maintenant, je n'ai pas encore vu de description des problèmes *précis* auxquels cela expose.
Il n'y a pas trop de problèmes, seul le nom des classes de bases est foireux. Comme l'explique Fabien Le Lez, "ObjetAyantUnePosition" est préférable à "Position". Pourquoi? Parce que ça évite des confusions pour les utilisateurs de la classe. Ainsi, si je lis "Position", je pense à une classe concrète, copiable et assignable, et bêtement j'aimerais pouvoir faire:
Position pos1; Position &pos2 = ..... pos2 = pos1;
Or pos2 peut-être une référence vers un Vehicule, et là c'est le bordel...
De mon côté, j'y vois le gros avantage de simplifier énormément les écritures et de limiter la quantité de code trivial, genre:
Position &Vehicule::GetPositionRef() { return this->position; }
Oui, pourquoi pas, on peut aussi éviter les duplications avec des macros:
class Vehicule { IMPLEMENTE_POSITION() IMPLEMENTE_COULEUR() };
et ce pour chaque attribut.
Rien ne vous oblige à écrire des "this->", déjà :)
-- C'est ma signature qu'elle est la mieux. Pas la vôtre.
Merci pour vos commentaires!
Je me doutais bien que beaucoup déconseilleraient ce design, mais
jusqu'à maintenant, je n'ai pas encore vu de description des problèmes
*précis* auxquels cela expose.
Il n'y a pas trop de problèmes, seul le nom des classes de bases est
foireux. Comme l'explique Fabien Le Lez, "ObjetAyantUnePosition" est
préférable à "Position".
Pourquoi? Parce que ça évite des confusions pour les utilisateurs de la
classe.
Ainsi, si je lis "Position", je pense à une classe concrète, copiable et
assignable, et bêtement j'aimerais pouvoir faire:
Position pos1;
Position &pos2 = .....
pos2 = pos1;
Or pos2 peut-être une référence vers un Vehicule, et là c'est le bordel...
De mon côté, j'y vois le gros avantage de simplifier énormément les
écritures et de limiter la quantité de code trivial, genre:
Je me doutais bien que beaucoup déconseilleraient ce design, mais jusqu'à maintenant, je n'ai pas encore vu de description des problèmes *précis* auxquels cela expose.
Il n'y a pas trop de problèmes, seul le nom des classes de bases est foireux. Comme l'explique Fabien Le Lez, "ObjetAyantUnePosition" est préférable à "Position". Pourquoi? Parce que ça évite des confusions pour les utilisateurs de la classe. Ainsi, si je lis "Position", je pense à une classe concrète, copiable et assignable, et bêtement j'aimerais pouvoir faire:
Position pos1; Position &pos2 = ..... pos2 = pos1;
Or pos2 peut-être une référence vers un Vehicule, et là c'est le bordel...
De mon côté, j'y vois le gros avantage de simplifier énormément les écritures et de limiter la quantité de code trivial, genre:
Rien ne vous oblige à écrire des "this->", déjà :)
OK, merci pour tous les avis!
En ce qui concerne les "this->" c'est une vieille habitude :)
Alain Gaillard
Je me doutais bien que beaucoup déconseilleraient ce design, mais jusqu'à maintenant, je n'ai pas encore vu de description des problèmes *précis* auxquels cela expose.
Ca viendra :)
De mon côté, j'y vois le gros avantage de simplifier énormément les écritures et de limiter la quantité de code trivial, genre:
Mais alors si tu veux simplifier, peut être que véhicule ne doit pas dériver de Position ni être composé, mais simplement avoir des membres xpos et ypos et alors c'est tout simplement
Je me doutais bien que beaucoup déconseilleraient ce design, mais
jusqu'à maintenant, je n'ai pas encore vu de description des problèmes
*précis* auxquels cela expose.
Ca viendra :)
De mon côté, j'y vois le gros avantage de simplifier énormément les
écritures et de limiter la quantité de code trivial, genre:
Mais alors si tu veux simplifier, peut être que véhicule ne doit pas
dériver de Position ni être composé, mais simplement avoir des membres
xpos et ypos et alors c'est tout simplement
Je me doutais bien que beaucoup déconseilleraient ce design, mais jusqu'à maintenant, je n'ai pas encore vu de description des problèmes *précis* auxquels cela expose.
Ca viendra :)
De mon côté, j'y vois le gros avantage de simplifier énormément les écritures et de limiter la quantité de code trivial, genre:
Mais alors si tu veux simplifier, peut être que véhicule ne doit pas dériver de Position ni être composé, mais simplement avoir des membres xpos et ypos et alors c'est tout simplement