30

La notion d'héritage est une notion de substitution (sauf heritage d'implementation, mais c'est a éviter):
http://en.wikipedia.org/wiki/Liskov_substitution_principle

Une classe virtuelle pure est une classe pour faire une normalisation d'interface, elle est utilisée dans énormément de design patterns dont le plus important:
http://www.design-up.com/articles/design/principesoo/dip.html

31

Les interfaces sont pas plutôt des classes abstraites ?
et quans je parlais de l'héritage virtuel je pensais à ce genre de déclaration :
classe A : virtual B {};
avatar

32

si, les interfaces sont des classes abstraites.

33

Mais qu'est-ce qu'une classe abstraite pour toi ? (et c'est la que le C++ est mal fini)

Une classe abstraite est une classe ou toutes les fonctions sont virtuelle pure... Ce n'est pas quelque chose de spécifique au C++, enfin, ce n'est pas un mot clef qui rend une classe "abstraite", et ce n'est d'ailleurs qu'une vision de l'esprit et pas reelemnet du language
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

34

La définition du C++ est que la classe est abstraite dès qu'il y a au moins une méthode virtuelle pure.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

35

c'est aussi celle du java.

une classe totalement abstraite devient alors une interface.

36

-> classe virtuelle pure.

Le mot interface n'existe pas en C++, on parle d'interface au niveau du design mais quand on parle de son implémentation cela devient une classe virtuelle pure.

37

38

Kevin Kofler (./34) :
La définition du C++ est que la classe est abstraite dès qu'il y a au moins une méthode virtuelle pure.

Oui pardon, c'est tellement mal foutu que je me suis emmeler les pinceaux...
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

39

Zephyr:et c'est plus puissant qu'un gros switch qui affecte sans distinction toutes les méthodes

(pas compris? tu parles des methodes virtuelles?)
Jackosking:Oui enfin s'il faut commencer a faire ce genre de bidouille on est pas sorti du cauchemar!

"bidouille"? trifus un #define override? grin
Sasume (./28) :
aze (./25) :
les classes virtuelles ça ne sert pas uniquement en cas d'héritage multiple ?
JackosKing (./26) :
non.
Euh si ?

? bah ca marche aussi pour de l'heritage simple, pas forcement multiple confus
Sinon je vois que personne a cité le nom liskov alors qu'il me semble que c'est la base pour bien commencer a faire de l'objet. (google: liskov principle)

connais pas... c'est encore un de ces noms attaches a des principes que tout le monde utilise sans forcement savoir comment ca s'appelle, mais qu'on t'apprend en ecole dans des cours purement theoriques? trifus
t'1 c'est un comme les design patterns ca... plein de noms speciaux dans tous les sens, meme pour des trucs simplistes dont tout le monde se sert naturellement au jour-le-jour tritop
avatar
HURRRR !

40

oui, je me suis rendu compte que je design patternais sans le savoir quand ma copine les a appris ^^

(par contre qu'est ce que c'est chiant a comprendre mvc sick )

41

Godzil (./38) :
Oui pardon, c'est tellement mal foutu que je me suis emmeler les pinceaux...

Bah, personnellement je trouve que le modèle objet du C++ est parfaitement intuitif, beaucoup plus que le modèle "simplifié" de VB, Java ou C# où un objet est toujours un pointeur et où par conséquent, quand on croit copier un objet, en réalité, on a un deuxième pointeur sur le même objet. Ça peut entraîner pas mal de bogues, ça. Le C++ distingue clairement les objets en eux-mêmes et les pointeurs ou références (où les références sont avant tout du "sucre syntaxique" pour les pointeurs).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

42

momotte (./39) :
Zephyr:et c'est plus puissant qu'un gros switch qui affecte sans distinction toutes les méthodes

(pas compris? tu parles des methodes virtuelles?)
Jackosking:Oui enfin s'il faut commencer a faire ce genre de bidouille on est pas sorti du cauchemar!

"bidouille"? trifus un #define override? grin
Sasume (./28) :
aze (./25) :
les classes virtuelles ça ne sert pas uniquement en cas d'héritage multiple ?
JackosKing (./26) :
non.
Euh si ?

? bah ca marche aussi pour de l'heritage simple, pas forcement multiple confus
Sinon je vois que personne a cité le nom liskov alors qu'il me semble que c'est la base pour bien commencer a faire de l'objet. (google: liskov principle)

connais pas... c'est encore un de ces noms attaches a des principes que tout le monde utilise sans forcement savoir comment ca s'appelle, mais qu'on t'apprend en ecole dans des cours purement theoriques? trifus
t'1 c'est un comme les design patterns ca... plein de noms speciaux dans tous les sens, meme pour des trucs simplistes dont tout le monde se sert naturellement au jour-le-jour tritop


Non, tu ferais peut etre bien de te renseigner non?
Justement je n'ai jamais appris ces concepts à l'école. Et c'est parce qu'on les apprend pas à l'école qu'on a des informaticiens qui programment n'importe comment!

43

Kevin Kofler (./41) :
Godzil (./38) :
Oui pardon, c'est tellement mal foutu que je me suis emmeler les pinceaux...

Bah, personnellement je trouve que le modèle objet du C++ est parfaitement intuitif, beaucoup plus que le modèle "simplifié" de VB, Java ou C# où un objet est toujours un pointeur et où par conséquent, quand on croit copier un objet, en réalité, on a un deuxième pointeur sur le même objet. Ça peut entraîner pas mal de bogues, ça. Le C++ distingue clairement les objets en eux-mêmes et les pointeurs ou références (où les références sont avant tout du "sucre syntaxique" pour les pointeurs).


Si tu copie ton objet comme ça tu risque d'avoir des surprises dans tout les languages quelque qu'il soit et tend a montrer que tu ne connais pas bien le concept objet. L'approche pointeur est bcp plus approprié pour l'objet que l'inverse... (je parle pas spécifiquement pour toi, mais en général)

Par contre les références, c'est clair que leur utilité :/
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

44

Vive les classes implicitly shared (copy on write) de Qt! On peut copier un objet comme ça (par exemple QString) comme si c'était par exemple un entier, et en interne la copie n'est effectuée que quand c'est nécessaire (quand on modifie une des copies), dans Qt 4 tout ceci fonctionne même en multithreadé (ils utilisent des compteurs de références atomiques).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

45

heu, tu trouves les reference pas utiles? hum
c'est peut etre du sucre syntaxique, mais la encore, un peu comme les override, c'est du sucre sans lequel ca marcherait pareil, mais qui aide incroyablement des qu'on considere la maintenabilite et la lisibilite du code. l'implementation est identique aux pointeurs, avec les avantages et les inconvenients que ca comporte, mais dans 99% des cas, tu peux assumer qu'une reference ne sera jamais nulle (et ne dois jamais etre nulle, si une reference devient nulle, c'est soit un bug serieux, soit un design tellement horrible que... bref.. (il faut vraiment le faire expres pour avoir des references nulles))

ca enleve de ton esprit le souci d'avoir a tester si le pointeur est null, a gerer ce cas, meme a y penser. c'est une facon explicite de dire "cette fonction ne prend jamais de pointeurs nulls, ca n'a pas de sens pour elle, et c'est invalide", de telle sorte que c'est explicite pour la personne qui s'en sert. (il y a peut etre aussi des possibilites d'optims que tu n'as pas avec les pointeurs classiques, lors des inlines, mais bon j'en suis pas sur (vu qu'a partir du moment ou c'est inline, le compilateur devrait a priori pouvoir aussi eliminer les dereferencements qu'il juge inutiles ou redondants lorsqu'il s'agit de pointeurs))

Jackosking> oui je suis alle voir ton lien, pour me renseigner effectivement, et... bah... et rien, ca n'a rien de particulierement special, c'est bien ce que je disais zzz
la c'est juste bien ecrit et enonce sous forme de notation pseudo-mathematique...
avatar
HURRRR !

46

http://doc.trolltech.com/qq/qq13-apis.html#pointersorreferences

Quant au problème de NULL, c'est à ça que sert __attribute__((nonnull)). smile
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

47

à satisfaire ceux qui aiment pas les références? grin

48

Only the first line makes it clear that there's a high probability that h, s, and v will be modified by the function call.

c'est pas faux, mais je trouve que ca peut etre genant uniquement lorsque tu ne constifie pas tes parametres lorsqu'ils peuvent l'etre. et ca depend beaucoup des habitudes de code que t'as, et de comment tu design tes classes/methodes... c'est sur que des classes designees pour etre tres facilement lisibles et utilisables avec des pointeurs ne passeront pas forcement bien avec des references point de vue lisibilite, et l'inverse est encore plus vrai, mais entre les deux options, perso je trouve quand meme les references plus claires et pratiques...

(et puis bon heu, leur exemple, excuse moi.. grin "getHSV(h, s, v)", tu t'attends a quoi en lisant ca, a ce que ca utilise les 3 valeurs que tu lui passe pour faire un truc en interne, ou a ce que ca te les remplisse ? #trihum# et si c'etait un "setHSV", les 3 seraient a priori const... (ou des valeurs passees directement) donc bon...)

sinon le "high probability", bah, a partir du moment ou les const sont utilises la ou il faut, tu as l'info directement dans la declaration de la fonction, et si tu utilises une IDE un minimum evoluee (style visual studio, par exemple grin), tu as l'info directement lorsque tu ecris l'appel a la methode...

et le probleme de NULL... entre "__attribute__((nonnull)) *", ou une syntaxe du meme genre et juste "&", on a vu mieux point de vue lisibilite quand meme.. non? grin enfin, si c'est bien comme ca que ca s'utilise / a ca que ca sert (surtout que si tu veux bien le faire, des nonnull, tu peux en avoir quasiment partout, donc si c'est pour remplacer toutes les references par des pointeurs taggues avec des __attribute__((nonnull)), je sais pas toi, mais ca me parait quand meme mieux les references grin)
avatar
HURRRR !

49

Merci beaucoup à vous tous pour vos conseils smile
Godzil (./43) :
Si tu copie ton objet comme ça tu risque d'avoir des surprises dans tout les languages quelque qu'il soit et tend a montrer que tu ne connais pas bien le concept objet. L'approche pointeur est bcp plus approprié pour l'objet que l'inverse... (je parle pas spécifiquement pour toi, mais en général)

Par contre les références, c'est clair que leur utilité :/

Perso j'ai tendance à penser que les références sont souvent utiles, mais uniquement lorsqu'on parle d'objets qui pourraient interagir avec l'extérieur ou qui doivent subsister plus loin que localement. Si je me crée par exemple un objet représentant un nombre à virgule fixe (ou un autre type de données du style) les valeurs sont mieux, ça évite aussi les memory leaks ^^
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

50

Godzil> Je crois qu'il y a eu quiproquo sur les "classes virtuelles" : aze parlait de la possibilité du C++ de faire de l'héritage virtuel (./31).
Kevin Kofler (./44) :
Vive les classes implicitly shared (copy on write) de Qt! On peut copier un objet comme ça (par exemple QString) comme si c'était par exemple un entier, et en interne la copie n'est effectuée que quand c'est nécessaire (quand on modifie une des copies), dans Qt 4 tout ceci fonctionne même en multithreadé (ils utilisent des compteurs de références atomiques).
Mouais justement je trouvais ça très bien au début aussi, mais en fait maintenant à chaque fois que j'utilise un objet Qt, j'en viens à me poser la question de savoir s'il est implicitement partagé ou non pour savoir comment je peux l'utiliser dans mon code sans affecter les performances. Du coup je suis obligé de vérifier, et je perds du temps, et puis le fait que ça crée deux niveaux d'objets ça fait que je suis obligé de produire deux styles de code selon les objets que je manipule, etc. Enfin bref, ça ne me fait pas vraiment gagner de temps (sauf pour QString parce que j'ai l'habitude avec celui-là mais c'est tout) et ça me conforte dans l'idée que le C++ est pénible à utiliser, vive les langages de plus haut niveau tel que le Java ou le Python ou ces problèmes ne se posent pas...
momotte (./45) :
Jackosking> oui je suis alle voir ton lien, pour me renseigner effectivement, et... bah... et rien, ca n'a rien de particulierement special, c'est bien ce que je disais zzz
la c'est juste bien ecrit et enonce sous forme de notation pseudo-mathematique...
Mais je trouve que c'est justement le fait de passer par cette étape de formalisation qui permet de prendre du recul sur ces concepts et nous rend capables de choisir judicieusement et rapidement quelle solution utiliser pour répondre à un problème donné. Cela prémâche toute réflexion éventuelle dans la génération de code.
Après, peut-être simplement que tu es doué et que tu réussis à faire ces opérations immédiatement quand tu es face à un pb, mais comme le dit Jackosking (et vu la nature des messages qu'il poste sur yN c'est probablement son cas), ça ouvre plein de portes aux personnes plus limitées intellectuellement qui n'auraient pas été capables de trouver ces solutions toutes seules.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

51

Ce n'est pas une question de personne limitée ou non. Comment veut tu discuter avec qqn de design si tu ne connais pas les différents patterns? Toutes les références des livres en OO se basent là dessus!
J'en conseille d'ailleur 2 formidables:
Agile Software Design de Martin
et
Refactoring to Pattern de J.Kerievsky

Le principe de liskov va plus loin car il est fortement lié à la programmation par contrat de Bertrand Meyer. Ce sont des méthodes qui permettent de faire du code de qualité et facilement maintenable. Après il y a toujours les 2 3 geek dans leurs coins qui pensent tout savoir, mais en générale cela ne va pas très loin et on se retrouve avec des gens qui dérivent un carré d'un rectangle triso.

En conclusion je dirais que le monde de l'informatique évolue vite, et qu'il est indispensable de lire et de se cultiver un peu sinon on est vite largué... :/ C'est d'ailleur la seul chose qui peut permettre de grarder l'informatique dans les pays développés.

52

y'en a un autre qui est bien c'est "design patterns la tête la première" (head first design patterns)

JK> oué mais toi apparemment t'as suivi des cours assez précis d'algorithmique, et c'est pas le cas de la majorité des programmeurs. Je dis pas que c'est glorieux (au contraire) mais c'est un fait. Et ces gens là ont plutot une vision empirique de la programmation.

et si tu refuses de discuter avec tous les mecs qui connaissent pas les arcanes des plus obscurs design patterns, ben... ça doit pas être gai grin

(bon je sais que je caricature, donc prenez ce que je dis un peu coolement ^^)

53

Non on me l'a enseigné au boulot parce que justement je l'ai pas appris avec mon école:/
Je ne suis pas un gourou des dp mais je pense avoir assez de recul pour dire que ca apporte un grand plus.
Après la personne peut ne pas connaître, le tout est qu'elle rattrape ses lacunes dans ce domaine et qu'elle apporte ses connaissances dans d'autres wink


54

ah, ok. Donc c'est plutot un truc dont t'as besoin dans le cadre de ton travail, qui doit être plus spécialisé que la moyenne. bien, bien!

sinon pencil pour dire que les dp sont un plus, mais le pb c'est que c'est pas du tout intuitif (c'est ça qui fait leur force) pour être appréhendés rapidement par tout le monde. Bon bref.

Sinon moi je voulais (un jour) générer un XML avec un pattern visiteur et je me suis trouvé con parce qu'il fallait visiter chaque noeud deux fois confus du coup je me suis sacrément refroidi, en voyant que ça sert à rien de vouloir en mettre partout.

sinon, mvc, une fois qu'on a compris, top et ça doit être pareil pour les autres j'imagine ^^

55

Je ne comprend pas bien ton problème avec le pattern visiteur. Tu peux donner un peu plus de détail?

56

momotte (./48) :
sinon le "high probability", bah, a partir du moment ou les const sont utilises la ou il faut, tu as l'info directement dans la declaration de la fonction

Ça ne vaut pas l'information que d'avoir les & dans chaque ligne qui utilise la fonction fournit!
et si tu utilises une IDE un minimum evoluee (style visual studio, par exemple grin), tu as l'info directement lorsque tu ecris l'appel a la methode...

Mais le code est lu bien plus souvent qu'écrit.
Sasume (./50) :
Mouais justement je trouvais ça très bien au début aussi, mais en fait maintenant à chaque fois que j'utilise un objet Qt, j'en viens à me poser la question de savoir s'il est implicitement partagé ou non pour savoir comment je peux l'utiliser dans mon code sans affecter les performances. Du coup je suis obligé de vérifier, et je perds du temps, et puis le fait que ça crée deux niveaux d'objets ça fait que je suis obligé de produire deux styles de code selon les objets que je manipule, etc. Enfin bref, ça ne me fait pas vraiment gagner de temps (sauf pour QString parce que j'ai l'habitude avec celui-là mais c'est tout) et ça me conforte dans l'idée que le C++ est pénible à utiliser

Pourtant, c'est simple, avec Qt 4 il n'y a que 2 types d'objet (Qt 3 était un peu plus bordélique, il y avait des classes explicitly shared):
* les objets dérivés de QObject. Ce sont les "vrais" objets, tout ce qui peut envoyer ou recevoir des évènements est un QObject. Ces objets sont normalement toujours utilisés sous forme de pointeurs (c'est une mauvaise idée d'avoir un QObject local parce qu'un QObject peut être libéré automatiquement si l'objet parent l'est, et aussi parce que ça consomme trop de place sur la pile), il est interdit de copier un QObject et l'héritage multiple est interdit (on peut bien sûr hériter d'un QObject + autre chose, mais pas de 2 dérivés de QObject). Ça se rapproche beaucoup au modèle d'objets du Java (mais en plus clair parce qu'il est toujours explicit qu'on manipule des pointeurs, pas directement des objets).
* les objets implicitly shared: ce sont les classes de données, ce sont donc des types de données de première classe, tout comme int, et peuvent s'utiliser de la même manière, sans se soucier du fait qu'il s'agit en réalité de classes, sauf qu'on peut appeler des méthodes de ces classes.
vive les langages de plus haut niveau tel que le Java ou le Python ou ces problèmes ne se posent pas...

En Java et Python tu as des chaînes de caractères immutables, c'est beaucoup moins pratique que l'implicitly shared. Le système de Qt te donne les mêmes avantages de performance (pas de copies inutiles) sans les limitations d'utilisation (qui se traduisent souvent par d'autres problèmes de performance, par exemple faire des concaténations de chaînes de caractères Java, ça rame!) qui vont avec.

Et si tu veux absolument des chaînes immutables, rien ne t'empêche de travailler avec des const QString, ça te donne essentiellement le même effet.
JackosKing (./51) :
et on se retrouve avec des gens qui dérivent un carré d'un rectangle triso.

Je ne vois rien de "triso" là, un carré est un rectangle... C'est l'inverse qui serait absurde (et pourtant ça se voit: "tiens, on a déjà le concept de longeur dans le carré, rajoutant un champ largueur et ça devient un rectangle"... mais du coup, quand on regarde le polymorphisme résultant, un rectangle serait un carré!?).

Ne peut-on pas résoudre le problème avec du copy on write ici aussi?
Carre c(4); // crée un objet Carre qui contient un CarrePrivate *
Rectangle r = c; // r est un Rectangle qui contient un RectanglePrivate * qui pointe sur CarrePrivate *
r.setWidth(3); // le RectanglePrivate est copié et modifié et Rectangle pointe maintenant sur un vrai RectanglePrivate et plus le CarrePrivate
c.setWidth(3); // error: Carre::setWidth(int) is private (c'est aussi simple que ça de supprimer une méthode d'une classe de base)
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

57

La notion de "est un" n'est pas ce qui définit l'héritage!
En effet la notion du principe de Liskov est plus restrictive car elle inclue le design par contrat.

Pour qu'une instance dérivée se substitue à une instance père, il faut:
> Que la classe dérivée n'exige pas plus à son utilisateur.
> Quel la classe dérivée ne garantisse pas moins à son utilisateur.

exiger/garantir: terme de design by contract.

Si tu regardes le contrat de setWidth: height constant.
Ce contrat est violé par le carré. Il implique que le principe de liskov n'est pas respecté et que ta classe carré ne passera pas le test unitaire de la classe rectangle.

58

Je suis aussi intéressé par ton triso JK, je ne vois pas en quoi c'est débile qu'un carré dérive d'un rectangle. Le carré n'est clairement qu'un cas particulier du rectangle...
[Edit] Ok, je sais pas pourquoi avant il n'y avait qu'un ; à la place de ton post...
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

59

JackosKing (./57) :
Si tu regardes le contrat de setWidth: height constant.

Donc il faut interdire d'appeler setWidth sur un carré, par exemple:
class Rectangle {
  public:
    virtual void setWidth(int);
}

class SquareVKiller : public Rectangle{
  public:
    virtual void setWidth(int) {throw "Invalid on a square";}
}

class Square : public SquareVKiller {
  private:
    void setWidth(int); // to detect the error at compile time where possible
}


Comment permettre de transformer un carré en un rectangle en ne changeant que la largeur? Ben, avec le système copy-on-write du ./56. Ici, la bonne solution pour avoir le polymorphisme est d'utiliser le copy constructor Rectangle::Rectangle(const Square &) qui utilise le polymorphisme de SquarePrivate en interne, mais si on écrit en utilisant les interfaces de la classe Rectangle, l'objet est détaché (copié) en tant que RectanglePrivate, pas SquarePrivate et les contrats de Rectangle sont remplis. (Et oui, on peut appeler Rectangle::setWidth parce que c'est une copie qui est effectuée, donc l'objet n'est plus de type Square ou SquareVKiller même si l'objet interne est toujours de type SquarePrivate avant le détachement.) Utiliser un Rectangle * est une mauvaise idée et en faisant ça, on risque de se taper l'exception si on a le malheur de tomber sur un carré, mais la solution est de ne pas utiliser un pointeur sur cette classe implicitly shared.

Le COW fonctionne ici parce qu'en lecture, un carré peut remplir toutes les fonctionnalités d'un rectangle, ce n'est qu'à l'écriture qu'on a une invariante supplémentaire.

Sinon, une solution encore plus simple est d'avoir des rectangles et carrés immutables, dans ce cas le problème de setWidth ne se pose même pas. Mais cette solution n'est pas toujours appliquable.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

60

Kevin Kofler (./59) :
JackosKing (./57) :
Si tu regardes le contrat de setWidth: height constant.
Donc il faut interdire d'appeler setWidth sur un carré, par exemple:


Non.