{"id":2848,"date":"2008-12-08T20:00:58","date_gmt":"2008-12-08T19:00:58","guid":{"rendered":"http:\/\/www.hyperbate.com\/dernier\/?p=2848"},"modified":"2008-12-08T20:00:58","modified_gmt":"2008-12-08T19:00:58","slug":"processing-treizieme-cours","status":"publish","type":"post","link":"https:\/\/hyperbate.fr\/dernier\/?p=2848","title":{"rendered":"Processing, treizi\u00e8me cours"},"content":{"rendered":"<p>La programmation orient\u00e9e objet est un concept relativement r\u00e9cent dans l&rsquo;histoire de l&rsquo;informatique (n&rsquo;ayant \u00e9t\u00e9 massivement employ\u00e9 que depuis le d\u00e9but des ann\u00e9es 1990, quoique l&rsquo;id\u00e9e soit bien plus ancienne) mais il semble \u00e0 pr\u00e9sent impossible de vivre sans. En effet, des applications aussi banales que les interfaces graphiques d&rsquo;ordinateurs ou la gestion des \u00e9l\u00e9ments d&rsquo;un jeu interactif rendent le recours \u00e0 ce \u00ab paradigme \u00bb\u00a0presque obligatoire. Un grand nombre de langages de programmation courants sont orient\u00e9s objet.<\/p>\n<p>Pour bien comprendre l&rsquo;int\u00e9r\u00eat de la programmation objet, prenons un cas simple et facile. Tout d&rsquo;abord, imaginons que nous voulions cr\u00e9er un stylo \u00ab\u00a0fou\u00a0\u00bb qui dessine sur notre fen\u00eatre d&rsquo;affichage.<\/p>\n<div class=\"code\">\n<pre>float x, y; <span class=\"rem\">\/\/ d\u00e9claration des variables d\u00e9cimales x et y<\/span>\n\nvoid setup(){\n\u00a0\u00a0<span class=\"rem\">\/\/ au d\u00e9marrage<\/span>\n\u00a0\u00a0size(180,180); <span class=\"rem\">\/\/ r\u00e9glage du format de la fen\u00eatre<\/span>\n\u00a0\u00a0background(0); stroke(255);\u00a0<span class=\"rem\">\/\/ r\u00e9glage des couleurs<\/span>\n\u00a0\u00a0x=90;y=90; <span class=\"rem\">\/\/affectation de valeurs \u00e0 x et y;\u00a0<\/span>\n}\n\nvoid draw(){\n<span class=\"rem\">\u00a0\u00a0\/\/ script ex\u00e9cut\u00e9 r\u00e9guli\u00e8rement\u00a0<\/span>\n\u00a0\u00a0float newx = x+random(-5,5);\u00a0 <span class=\"rem\">\/\/ cr\u00e9ation de newx<\/span>\n\u00a0\u00a0float newy = y+random(-5,5);\u00a0 <span class=\"rem\">\/\/ cr\u00e9ation de newy<\/span>\n<span class=\"rem\">\u00a0\u00a0\/\/ contraintes appliqu\u00e9es \u00e0 newx et newy<\/span>\n<span class=\"rem\">\u00a0\u00a0\/\/ afin de les emp\u00eacher de sortir de l'\u00e9cran\u00a0<\/span>\n\u00a0\u00a0if(newx&lt;0){newx=0;}\u00a0if(newx&gt;width){newx=width;}\n\u00a0\u00a0if(newy&lt;0){newy=0;}\u00a0if(newy&gt;height){newy=height;}\n<span class=\"rem\">\u00a0\u00a0\/\/ trac\u00e9 de la ligne<\/span>\n\u00a0\u00a0line (x, y, newx, newy);\n<span class=\"rem\">\u00a0\u00a0\/\/ enfin, x prend la valeur de newx et y celle de newy<\/span>\n\u00a0\u00a0x = newx; y = newy;\n}<\/pre>\n<\/div>\n<p><img decoding=\"async\" class=\"imageadroite\" src=\"\/dernier\/files\/2008\/12\/dessin_fou_1.png\" alt=\"\" width=\"180\" height=\"180\" align=\"right\" \/><\/p>\n<p>Le r\u00e9sultat d&rsquo;un tel script sera le trac\u00e9 totalement au hasard d&rsquo;un trait blanc sur un fond noir. L&rsquo;image ci-contre montre une capture de l&rsquo;image de la \u00ab\u00a0sc\u00e8ne\u00a0\u00bb \u00e0 un moment du d\u00e9roulement du programme. La fen\u00eatre fait 180&#215;180 pixels et le trac\u00e9 commence en son centre c&rsquo;est \u00e0 dire au point (90,90). \u00c0 chaque cycle, un nouveau point est calcul\u00e9, qui s&rsquo;\u00e9loigne de la position pr\u00e9c\u00e9dente \u00e0 une distance variant entre -5 et +5 pixels dans les abscisses et entre -5 et +5 pixels dans les ordonn\u00e9es.<br \/>\nOn note qu&rsquo;\u00e0 chaque cycle, une fois que les valeurs newx (x + random(-5,5)) et newy (y + random(-5,5)) ont \u00e9t\u00e9 calcul\u00e9es, la ligne est trac\u00e9e avant que x soit remplac\u00e9 par newx et y par newy.<\/p>\n<p>Ce script tr\u00e8s simple ne s&rsquo;adapte cependant qu&rsquo;au seul et unique cas o\u00f9 nous n&rsquo;aurions qu&rsquo;un seul traceur \u00ab\u00a0fou\u00a0\u00bb \u00e0 utiliser. Mais comment faire pour tracer plusieurs traits en m\u00eame temps, de plusieurs couleurs diff\u00e9rentes en m\u00eame temps ? C&rsquo;est pr\u00e9cis\u00e9ment l\u00e0 qu&rsquo;intervient la programmation objet, elle me permet de d\u00e9cr\u00e9ter l&rsquo;existence d&rsquo;un objet nomm\u00e9 \u00ab\u00a0traceur_fou\u00a0\u00bb qui existera simultan\u00e9ment en plusieurs occurrences (ou instances), comme suit :<\/p>\n<div class=\"code\">\n<pre>traceur_fou[] traceurs = new traceur_fou[0]; <span class=\"rem\">\n\/\/ d\u00e9claration d'un tableau de type \"traceur_fou\"\n\/\/ ce tableau se nomme traceurs a au d\u00e9part z\u00e9ro \u00e9l\u00e9ments <\/span>\n\nvoid setup(){\n  <span class=\"rem\">\/\/ d\u00e9marrage<\/span>\n  size(180,180); <span class=\"rem\"> \/\/ r\u00e9glage du format de la fen\u00eatre<\/span>\n  background(0); stroke(255); <span class=\"rem\"> \/\/ r\u00e9glage des couleurs<\/span>\n  <span class=\"rem\"> \/\/ cr\u00e9ation de dix objets de type traceur_fou<\/span>\n  <span class=\"rem\"> \/\/ qui sont ajout\u00e9s au tableau traceurs <\/span>\n  for(int a=0;a&lt;10;a++){\n    traceurs = (traceur_fou[]) append(traceurs, new traceur_fou());\n  }\n}\n\nvoid draw(){\n <span class=\"rem\">  \/\/ de mani\u00e8re r\u00e9guli\u00e8re (draw())\n   \/\/ une boucle permet de donner \u00e0 chaque objet de type traceur_fou <\/span>\n <span class=\"rem\">  \/\/ l'ordre d'activer sa commande dessine() <\/span>\n  for(int a=0;a&lt;traceurs.length;a++){\n   traceurs[a].dessine();\n }\n}\n\nclass traceur_fou{\n  \/\/ d\u00e9claration des variables dont disposera chaque objet de type\n  \/\/ traceur_fou\n  float x=90;float y=90;color c;\n  traceur_fou(){\n   <span class=\"rem\">  \/\/ \"constructeur\" d'objets de type traceur_fou\n     \/\/ ici, la couleur \"c\" prend une valeur au hasard <\/span>\n     c=color(random(255),random(255),random(255));\n  }\n  void dessine(){\n   <span class=\"rem\">  \/\/ dans le script \"dessine\" nous avons les \u00e9l\u00e9ments\n     \/\/ utilis\u00e9s dans le pr\u00e9c\u00e9dent programme <\/span>\n     stroke(c);\n     float newx = x+random(-5,5);\n     float newy = y+random(-5,5);\n     if(newx&lt;0){newx=0;} if(newx&gt;width){newx=width;}\n     if(newy&lt;0){newy=0;} if(newy&gt;height){newy=height;}\n     line (x, y, newx, newy);\n     x = newx; y = newy;\n  }\n}<\/pre>\n<\/div>\n<p><img decoding=\"async\" class=\"imageadroite\" src=\"\/dernier\/files\/2008\/12\/dessin_fou_2.png\" alt=\"\" width=\"180\" height=\"180\" align=\"right\" \/>J&rsquo;ai tent\u00e9 d&rsquo;\u00e9crire un programme tr\u00e8s simple mais je m&rsquo;aper\u00e7ois que sa lisibilit\u00e9 est assez relative. On peut en voir l&rsquo;effet sur l&rsquo;image qui se trouve ci-contre et qui est une capture de l&rsquo;image de la sc\u00e8ne \u00e0 un moment de l&rsquo;ex\u00e9cution du programme. Au lieu de tracer un trait au hasard, notre programme en trace dix en m\u00eame temps. Chacun a sa couleur propre, attribu\u00e9e au hasard.<\/p>\n<p>Le secret d&rsquo;un tel programme est l&rsquo;utilisation des \u00ab\u00a0classes\u00a0\u00bb d&rsquo;objets. Une classe est un ensemble de propri\u00e9t\u00e9s de types disparates (une m\u00eame classe peut contenir des chiffres, des cha\u00eenes de caract\u00e8res, etc.) et de fonctions qui peuvent \u00eatre attribu\u00e9es \u00e0 plusieurs occurrences ind\u00e9pendantes.<br \/>\nPour prendre une m\u00e9taphore assez simple, nous pouvons dire que chacun d&rsquo;entre nous est une occurrence unique de la classe \u00ab\u00a0\u00eatre humain\u00a0\u00bb. Nous avons de nombreux points en commun mais nous sommes tous diff\u00e9rents par certains aspects : notre nom, notre \u00e2ge, notre identit\u00e9 sexuelle, notre couleur de cheveux, etc. Nous sommes tous capables d&rsquo;ex\u00e9cuter certaines fonctions de mani\u00e8re ind\u00e9pendante (marcher, courir, parler, etc.) ou simultan\u00e9e (vieillir). Si je voulais cr\u00e9er une classe d&rsquo;\u00eatre humain disposant des propri\u00e9t\u00e9s et des fonctions \u00e9num\u00e9r\u00e9es ci dessus, je la r\u00e9digerais par exemple ainsi :<\/p>\n<div class=\"code\">\n<pre>class etre_humain{\n\u00a0\u00a0String nom, sexe, cheveux; int age;\n\u00a0\u00a0\u00a0etre_humain (String n, String s, String c, int a){\n\u00a0\u00a0 \u00a0 \u00a0nom = n; sexe = s; cheveux = c; age = a;\n\u00a0\u00a0 }\n\u00a0\u00a0void \u00a0vieillis(){\n\u00a0\u00a0 \u00a0 \u00a0age = age+1;\n\u00a0\u00a0}\n\u00a0\u00a0void marche(){\n\u00a0\u00a0 \u00a0 \u00a0<span class=\"rem\">\/\/ ...commandes correspondant au fait de marcher<\/span>\n\u00a0\u00a0}\n}<\/pre>\n<\/div>\n<p>Je peux \u00e0 pr\u00e9sent \u00ab\u00a0cr\u00e9er\u00a0\u00bb des instances de l&rsquo;objet \u00ab\u00a0etre_humain\u00a0\u00bb de cette mani\u00e8re :<\/p>\n<div class=\"code\">\n<pre>etre_humain \u00a0eh1 = new etre_humain(\"Georges\", \"homme\", \"brun\", 40);\netre_humain \u00a0eh2 = new etre_humain(\"Charles\", \"homme\", \"brun\", 50);\netre_humain \u00a0eh3 = new etre_humain(\"Lucille\", \"femme\", \"blond\", 32);\netre_humain \u00a0eh4 = new etre_humain(\"Charlotte\", \"femme\", \"chatain\", 36);<\/pre>\n<\/div>\n<p>Chaque instance est stock\u00e9e dans une variable. J&rsquo;ai nomm\u00e9 mes variables <code>eh1<\/code>, <code>eh2<\/code>, <code>eh3<\/code> et <code>eh4<\/code>, mais j&rsquo;aurais pu leur donner d&rsquo;autres noms bien entendu. \u00c0 pr\u00e9sent, si je d\u00e9sire conna\u00eetre l&rsquo;\u00e2ge de Georges (qui est stock\u00e9 dans\u00a0<code>eh1<\/code>), je n&rsquo;aurais qu&rsquo;\u00e0 demander <code><strong>print(eh1.age);<\/strong><\/code>. Si je d\u00e9sire changer la couleur des cheveux de Charlotte je peux \u00e9crire : <code><strong>eh4.cheveux = \"roux\";<\/strong><\/code>.<br \/>\nEnfin, si je souhaite faire vieillir Charles d&rsquo;un an, je peux \u00e9crire <code><strong>eh2.vieillis();<\/strong><\/code>.<br \/>\nCe genre d&rsquo;exemple est un peu abstrait puisque nous ne parlons ici que de valeurs num\u00e9riques ou de cha\u00eenes de caract\u00e8res. La programmation orient\u00e9e objet est souvent un peu difficile \u00e0 comprendre au d\u00e9but.<br \/>\nVoici une derni\u00e8re d\u00e9monstration d&rsquo;utilisation du paradigme \u00ab\u00a0orient\u00e9 objet\u00a0\u00bb.<\/p>\n<div class=\"code\">\n<pre><span class=\"rem\">\/\/ d\u00e9claration d'une liste d'objets de type \"cercle\"<\/span>\ncercle[] TousMesCercles = new cercle[0];\n\nvoid setup(){\n  size(180,180); smooth(); strokeWeight(0.5); background(255);\n  fill(255,25); <span class=\"rem\">\/\/ la couleur de remplissage est du blanc \u00e0 ~10% d'opacit\u00e9<\/span>\n  <span class=\"rem\">\/\/ remplissage du tableau TousMesCercles avec 89 objets de type \"cercle\"<\/span>\n  for(int a=1;a&lt;90;a++){\n    TousMesCercles = (cercle[]) append(TousMesCercles, new cercle(a));\n  }\n}\n\nvoid draw(){\n  noStroke();\n  rect(0,0,180,180);\n  stroke(0);\n  for(int a=0;a&lt;TousMesCercles.length;a++){\n    TousMesCercles[a].dessine();\n  }\n}\nclass cercle{\n  <span class=\"rem\">\/\/ d\u00e9claration des variables<\/span>\n  float rayon; float vitesse; float angle;\n  cercle(float r){\n    <span class=\"rem\">\/\/ initialisation de l'instance<\/span>\n    rayon=r; angle=0; vitesse=radians(random(-3,3));\n  }\n  void dessine(){\n    <span class=\"rem\">\/\/ fonction \"dessine\" propre \u00e0 chaque objet<\/span>\n    angle+=vitesse; \/\/ la variable \"angle\" est incr\u00e9ment\u00e9e de \"vitesse\"\n    <span class=\"rem\">\/\/ petit calcul trigonom\u00e9trique basique<\/span>\n    line(90,90,90+cos(angle)*rayon, 90+sin(angle)*rayon);\n  }\n}<\/pre>\n<\/div>\n<p><img decoding=\"async\" class=\"imageadroite\" src=\"\/dernier\/files\/2008\/12\/objets_traits_fade.png\" alt=\"\" width=\"180\" height=\"180\" align=\"right\" \/>Cette fois, nous avons cr\u00e9\u00e9 une classe nomm\u00e9e \u00ab\u00a0cercle\u00a0\u00bb (nous avons invent\u00e9 ce nom) qui utilise trois variables (nomm\u00e9es <code>rayon<\/code>, <code>vitesse<\/code> et <code>angle<\/code>, toutes de type \u00ab\u00a0float\u00a0\u00bb) et qui contient deux fonctions, son \u00ab\u00a0constructeur\u00a0\u00bb\u00a0(sa fonction d&rsquo;initialisation), nomm\u00e9 <code>cercle()(c'est \u00e0 dire ayant le m\u00eame nom que la classe) <\/code>et une fonction nomm\u00e9e <code>dessine()<\/code>.<br \/>\nUne liste nomm\u00e9e \u00a0TousMesCercles est d\u00e9clar\u00e9e en t\u00eate du script puis remplie de 89 \u00e9l\u00e9ments dans la fonction <code>setup()<\/code>. Chacun de ces \u00e9l\u00e9ments s&rsquo;est fait attribuer une variable nomm\u00e9e rayon et allant de 1 \u00e0 90. voit invoquer sa fonction <code>dessine()<\/code> depuis la fonction <code>draw()<\/code>.<br \/>\nLa fonction <code>dessine()<\/code> incr\u00e9mente la variable angle en l&rsquo;additionnant \u00e0 la variable vitesse. Enfin une ligne est trac\u00e9e entre le centre <code>(90,90)<\/code> et un point calcul\u00e9 \u00e0 partir de l&rsquo;angle et du rayon <code>(90+cos(angle)*rayon, 90+sin(angle)*rayon)<\/code>. Nous reverrons peut-\u00eatre cette formule trigonom\u00e9trique de base ult\u00e9rieurement.<br \/>\nAu d\u00e9but de la fonction <code>draw()<\/code>, la sc\u00e8ne n&rsquo;est pas repeinte en blanc mais juste recouverte d&rsquo;un rectangle blanc \u00e0 10% d&rsquo;opacit\u00e9, ce qui donne un effet de persistance et d&rsquo;effacement progressif des traits trac\u00e9s. L&rsquo;image qui se trouve ci-contre correspond \u00e0 une capture de l&rsquo;\u00e9cran \u00e0 un moment donn\u00e9 de l&rsquo;animation mais vous devez copier-coller l&rsquo;ensemble du code dans Processing pour en voir l&rsquo;effet v\u00e9ritable.<\/p>\n<p>Il est en tout cas important de noter que les op\u00e9rations r\u00e9alis\u00e9es sur un tableau d&rsquo;objets ne peuvent \u00eatre r\u00e9dig\u00e9es comme suit :<\/p>\n<div class=\"code\">\n<pre>monTableau = append (monTableau, monObjet);<\/pre>\n<\/div>\n<p>mais doivent l&rsquo;\u00eatre de cette mani\u00e8re :<\/p>\n<div class=\"code\">\n<pre>monTableau = (classe[]) append(monTableau, monObjet);<\/pre>\n<\/div>\n<p>il est \u00e0 noter aussi que le mot-cl\u00e9 <code>this<\/code> est valide dans Processing. Ce mot-cl\u00e9 sert, pour un objet, \u00e0 se d\u00e9signer lui-m\u00eame. C&rsquo;est l&rsquo;\u00e9quivalent de <code>me<\/code> dans le logiciel Director. Ainsi un objet pourrait s&rsquo;ajouter de lui-m\u00eame \u00e0 une liste d&rsquo;objets comme ceci :<\/p>\n<div class=\"code\">\n<pre>bidule[] TousMesTrucs = new bidule[0];\n\nclass bidule{\n\u00a0\u00a0bidule(){\n\u00a0\u00a0 \u00a0\u00a0TousMesTrucs = (bidule[]) append (TousMesTrucs , this);\n\u00a0\u00a0}\n}<\/pre>\n<\/div>\n<p>Si vous n&rsquo;avez pas compris grand chose \u00e0 cet article, pas de panique. Ces concepts sont souvent difficiles \u00e0 assimiler. Le prochain article sera nettement plus accessible.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>La programmation orient\u00e9e objet est un concept relativement r\u00e9cent dans l&rsquo;histoire de l&rsquo;informatique (n&rsquo;ayant \u00e9t\u00e9 massivement employ\u00e9 que depuis le d\u00e9but des ann\u00e9es 1990, quoique l&rsquo;id\u00e9e soit bien plus ancienne) mais il semble \u00e0 pr\u00e9sent impossible de vivre sans. En effet, des applications aussi banales que les interfaces graphiques d&rsquo;ordinateurs ou la gestion des \u00e9l\u00e9ments [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40],"tags":[],"class_list":["post-2848","post","type-post","status-publish","format-standard","hentry","category-processing"],"_links":{"self":[{"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=\/wp\/v2\/posts\/2848","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2848"}],"version-history":[{"count":0,"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=\/wp\/v2\/posts\/2848\/revisions"}],"wp:attachment":[{"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hyperbate.fr\/dernier\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}