1020

Je bosse vraiment.. enfin pas aujourd'hui :P

1021

JackosKing (./1018) :
Exemple: Un carré est un rectangle, mais saurais tu me faire un heritage correcte entre ces deux types d'objet?

C'est le problème qui revient classiquement, et pour moi le principe générale de l'héritage "est un" n'est pas une règle absolue. I.e. c'est vrai mathématiquement qu'un carré est un rectangle, mais un carré ne se manipule pas de manière compatible avec le rectangle (du moins concernant la transformation) donc la généralisation au sens polymorphisme est à prendre avec des pincettes.
=> Un carré immuable est un rectangle immuable, mais un rectangle "mutable" non ^^
Cela dit je ne connais pas de relation d'héritage vraiment satisfaisante pour ces deux éléments, mais si tu en as une c'est volontiers smile
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

1022

Brunni (./1021) :
C'est le problème qui revient classiquement
Oué, même sur yN => topics/159-107111-gerer-les-objets-avec-des-classes/2#50

1023

^^
Sinon que dire de ça?
abstract class Rectangular { protected int width, height; int getWidth() { return width; } int getHeight() { return height; } } class Rectangle extends Rectangular { int setWidth(int w) { width = w; } int setHeight(int h) { height = h; } } class Square extends Rectangular { int setSize(int s) { width = height = s; } }
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

1024

captain obvious to the rescue.

mais l'abstract je vois pas a quoi elle sert. Le rectangle est pas assez grand pour assumer tout seul sa rectanglitude?

a la limite que rectangular s'appelle rectangle et dérive de parallélogramme ou polygone ou shape je voudrais bien, mais là, trifus

1025

Bah, une hiérarchie complète, c'est:
abstract class AbstractRectangle {
  public int getWidth();
  public int getHeight();
}

abstract class AbstractSquare extends AbstractRectangle {
  public int getSideLength();
}

interface ModifySquare {
  public void setSideLength(int l);
}

interface ModifyRectangle extends ModifySquare {
  public void setWidth(int w);
  public void setHeight(int h);
}

class Rectangle extends AbstractRectangle implements ModifyRectangle {
}

class Square extends AbstractSquare implements ModifySquare {
}

(J'ai volontairement omis les implémentations, je montre juste les interfaces.)

Ça résout le problème de l'héritage inversé en écriture.
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é

1026

Le langage objet offre des multitudes de possibilités pour écrire un programme mais aucune n'est parfaitement adaptée quand on recoupe les points de vue des différents développeurs...
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

1027

Je laisse folco proposer qqc avant de commenter wink

1028

T'es sûr ? grin

Je suis trop nul encore pour voir tous les tenants et aboutissants de ce problème. D'ailleurs si je l'ai pas trouvé très dur, c'est parce que je suis sûrement passé à côté de là où ça coince. grin
Mais si tu y tiens, je peux montrer ce que j'ai en tête (et qui tient sûrement du hello world, pas de la solution presque bien mais sur laquelle on peut quand même pinailler grin).

1029

J'ai pas dit que c'était dur hein wink

1030

squalyl (./1024) :
captain obvious to the rescue.

Excuse-moi d'en être encore à des problématiques si basiques...
squalyl (./1024) :
mais l'abstract je vois pas a quoi elle sert. Le rectangle est pas assez grand pour assumer tout seul sa rectanglitude?

Je ne comprends pas ce que tu veux dire confus
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

1031

quel besoin d'une interface dans l'exemple que t'as donné?

1032

Ben pour les getters width/height? Tu aurais préféré que je mette la même chose dans Rectangle et Square peut être?
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

1033

J'avais deviné !
• Folco content trilove


Quant à la solution de Kevin, c'est symétrique, c'est pour pouvoir dériver l'un à partir de l'autre dans les deux sens ?

1034

public class rectangle {
private int w;
private int h;
public rectangle(int wi, int he) { w=wi; h=he;}
public int getWidth() {return w;}
public int getHeight() {return h;}
public void setWidth(int wi) { w= wi;}
public void setHeight(int he) {h=he;}
}

public class carré extends rectangle {
public carré(int cote) { super(cote,cote); }
public void setcote(int cote) {setWidth(cote); setHeight(cote); }
}

et hop fini

1035

Ouais, j'ai la même que squalyl.
avatar

1036

QUOI?

carré c = new carré(10);
c.setWidth(20);

-> on a un carré de 20x10... et après je suis captain obvious?
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

1037

Ah mais il n'a pas surchargé les méthodes parce que c'est trivial embarrassed
avatar

1038

Avec un throw new UnsupportedException?
(je trouverais ça sale)
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

1039

Bah j'aurais pas fait exactement comme squalyl en fait, tiens... j'aurais surchargé les méthodes setWidth et setHeight pour qu'elles aient le même comportement (c'est à dire son setcote, quoi). Pas besoin d'un setcote.
avatar

1040

bon en fait je vois pourquoi c'était pas obvious que ça. faut surcharger en effet, soit en affectant la même chose a chaque membre, soit en unsupportedException, soit je comprends ta méthode à 3 classes.

j'avais pas pensé que les setters du rectangle foutraient le box dans le carré.

ok, mea culpa.

1041

Folco (./1033) :
Quant à la solution de Kevin, c'est symétrique, c'est pour pouvoir dériver l'un à partir de l'autre dans les deux sens ?

C'est pour pouvoir utiliser un carré comme un rectangle en lecture, mais un rectangle comme un carré en écriture. Le carré étant le concept plus particulier, avec un invariant de plus, en lecture c'est un cas particulier du rectangle, mais en écriture c'est la classe rectangle qui permet de changer plus de choses.
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é

1042

[nosmile]D'ailleurs, dans l'autre topic, j'ai proposé une solution qui repose sur le partage implicit (copy on write): on "copie" un Square dans un Rectangle, l'objet pointé n'est pas copié, c'est toujours un carré, on utilise setWidth et paf, le rectangle pointe maintenant sur un RectanglePrivate et on n'a pas touché au SquarePrivate. La classe SquarePrivate dérive de RectanglePrivate, donc on peut utiliser le carré comme un rectangle en lecture sans le copier, l'écriture force de toute façon une copie.

Maintenant, que faire pour éviter qu'on fasse des conneries avec le polymorphisme des pointeurs (Rectangle *)? Bah, soit on fait comme j'ai décrit dans l'autre topic (méthode virtuelle qui lance une exception si on l'utilise comme un carré), soit tout simplement on ne fait pas hériter Square de Rectangle, juste SquarePrivate de RectanglePrivate, et on utilise un Square:embarrassedperator Rectangle ou un Rectangle::Rectangle(const Square &) pour faire la conversion transparente.
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é

1043

Kevin, toi qui n'aime pas faire de l'objet et n'en fais pratiquement pas, tu voudrais pas me filer tes compétences stp ? Ca me trouducute, le gars il s'entraine pas et il roxamort, c'et limite décourageant ^^

1044

Nil (./1039) :
Bah j'aurais pas fait exactement comme squalyl en fait, tiens... j'aurais surchargé les méthodes setWidth et setHeight pour qu'elles aient le même comportement (c'est à dire son setcote, quoi). Pas besoin d'un setcote.

Pareil
avatar
<<< Kernel Extremis©®™ >>> et Inventeur de la différence administratif/judiciaire ! (©Yoshi Noir)

<Vertyos> un poil plus mais elle suce bien quand même la mienne ^^
<Sabrina`> tinkiete flan c juste qu'ils sont jaloux que je te trouve aussi appétissant

1045

Moi j'aurai employé un modèle simple, la solution ressemble un peu à celle de Brunni (je détaillerai après le bout de code)public abstract class RectangleBase { public abstract int Width { get; } public abstract int Height { get; } public int GetPerimeter { return 2 * (Width + Height); } public int GetSurface { return Width * Height; } } public class Rectangle : RectangleBase { private int width; private int height; public sealed int Width { get { return width; } set { if (value < 0) throw new ArgumentOutOfRangeException("value"); width = value; } } public sealed int Height { get { return height; } set { if (value < 0) throw new ArgumentOutOfRangeException("value"); height = value; } } } public class Square : RectangleBase { private int size; public sealed int Width { get { return size; } set { if (value < 0) throw new ArgumentOutOfRangeException("value"); size = value; } } public sealed int Height { get { return size; } set { Width = value; } } }Rien que pour ça y'a plein de variantes et je n'aurai probablement même pas utilisé ce modèle, car celui à utiliser précisément du contexte.
Ensuite, je reproche un truc à cette question, c'est qu'elle te force à penser héritage. Mais en fait si on y réfléchit bien c'est une mauvaise solution. Dans sa nature, un carré est un type spécial de rectangle, donc on pense héritage.
Mais avec de l'héritage, un rectangle peut également être un carré sans que celui-ci soit de classe carré (ça peut être désirable pour certains cas quand même hein)… Rien que ça moi, ça m'incite à penser que la meilleure solution pour représenter un rectangle ou un carré, c'est juste de ne pas avoir de classe carré. Si on y réfléchit bien ce que ça veut dire, c'est qu'on veut un rectangle qui soit contraint à être un carré, ou un rectangle qui ne soit pas contraint.
En fait la « solution parfaite » je pense, est celle d'un rectangle avec contraintes, ce qui colle plus à ce qu'on veut en vrai: De base, un rectangle est un rectangle, mais on peut lui appliquer une contrainte (je vous laisse réfléchir à la façon de faire, avec un champ booléen isSquare, ou bien avec une objet externe dérivé de IRectangleConsraint…), et ce éventuellement de manière dynamique (appliquer et annuler la contrainte à la volée), mais en aucun cas on n'a de type Square ou autre…
Il me semble que cette approche est plus proche de la réalité que les autres, mais bon, à vous de voir. (Je trouve _vraiment_ le modèle d'héritage non adapté pour cette situation)
À mon avis vous cherchez tous des solutions plus moisies les unes que les autres (cf ./1042 …) pour quelque chose qui n'en mérite pas tant tongue

(PS: j'aime quand même bien le modèle que j'ai proposé, je résout pas mal de problèmes avec ce modèle simple… Juste pas ce cas précis.)
[EDIT] J'avais oublié de modifier le copier coller pour la surface… vous n'avez rien vu… cheeky
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1046

C’est immonde de lancer une exception…
La solution de Kevin me semble la meilleure.
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. »

1047

C'est vrai que c'est tellement bien d'avoir un rectangle de côté négatifs… Oulàlà c'est certainement mieux que de lancer une « immonde » exception parfaitement justifiée… roll
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

1048

En effet c'est très complet ^^
Ca ressemble à ma solution sauf que j'ai compacté au maximum juste pour montrer, et donc je me suis pas embêté ^^ (genre les membres width/height protected c'est pas terrible)
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

1049

./1047 Ah oui en fait j’avais lu en diagonale. Ta solution me semble équivalente à celle de Kevin.
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. »

1050

./1047 : Justifié ou pas, c'est pas super malin d'avoir surchargé le code avec une gestion d'exception qui n'apporte strictement rien au problème dont il est question ici ^^ (et je ne parle pas des "sealed" et autres qui alourdissent la lecture, rendent le programme moins compréhensible pour quelqu'un qui ne parle le C#, et n'apportent rien eux non plus).

Sinon la solution qui me semble la meilleure est celle de Kevin également, à l'exception près que j'aurais laissé Square posséder les méthodes "getWidth" et "getHeight" au lieu de les remplacer par "getSideLength" (ça permet d'accéder en lecture à un carré comme à un rectangle sans se poser plus de questions) :
interface Rectangular { public int getHeight (); public int getWidth (); } class Rectangle implements Rectangular { private int h; private int w; public int getHeight () { return this->h; } public int getWidth () { return this->w; } public void setHeight (int h) { this->h = h; } public void setWidth (int w) { this->w = w; } } class Square implements Rectangular { private int l; public int getHeight () { return this->l; } public int getWidth () { return this->l; } public void setSideLength (int l) { this->l = l; } }

[edit 1] ah bah c'est quasiment la solution de Brunni en fait, j'avais mal lu, sauf que je préfère ne pas conserver deux variables distinctes dans Square, puisque ça introduit une incohérence possible qu'il est aussi simple d'éviter.

[edit 2] décidément j'ai lu n'importe comment, la solution de Kevin laisse getWidth et getHeight à la classe Square, donc je n'ai rien à reprocher ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)