340 likes | 424 Views
Héritage par prototype. Héritage d’attributs ou de méthodes Héritage de constructeurs. Héritage de méthodes. function Constructeur() { this . m1 = function () { . . . } } Constructeur.prototype. m2 = function () { . . . } var x = new Constructeur() var y = new Constructeur()
E N D
Héritage par prototype Héritage d’attributs ou de méthodes Héritage de constructeurs
Héritage de méthodes function Constructeur() {this.m1 = function () { . . . }} Constructeur.prototype.m2 = function () { . . . } var x = new Constructeur() vary = new Constructeur() x.m2() y.m2() prototype m2() objet construit this.m1 objet construit this.m1 m1() x m1() y Le lien n’est pas directement accessible par le programme Un sous-objet (attribut) prototype est automatiquement créé dans chaque fonction
Héritage de méthodes function Constructeur() {this.m1 = function () { . . . }} Constructeur.prototype.m2 = function () { . . . } var x = new Constructeur() Constructeur.prototype.m3 = function () { . . . } // après la création x.m1() x.m2() x.m3() prototype m2() m3() Constructeur this.m1 m1()
Héritage d’attributs function Constructeur() {this.a = 12} Constructeur.prototype.b = 13 var x = new Constructeur() Constructeur.prototype.c = 14 alert ( x.a +" " + x.b+" "+x.c) prototype b c 13 14 x objet construit this.a 12
Ré-écriture des attributs ! function Constructeur() {} Constructeur.prototype.a = 13 var x = new Constructeur()vary = new Constructeur() alert(x.a) // 13 x.a = 14alert(x.a) // 14 alert(y.a) // 13 prototype a 13 x.a = 14 x objet construit this.a 14 Chaque objet lit la valeur initiale, jusqu’à ce qu’il la change. Chaque objet a sa propre valeur.
Tableaux ou objet dans les prototypes ! function Constructeur() {} Constructeur.prototype.a = [ ] var x = new Constructeur() vary = new Constructeur() x.a[0] = 13 alert( y.a[0] ) // aussi 13 prototype a [13] Constructeur objet construit x y Les tableaux et les objets sont donc mis en commun
Création d’un nouveau tableau ou objet dans un prototype function Constructeur() {} Constructeur.prototype.a = [12] var x = new Constructeur() vary = new Constructeur() x.a = [8] // nouvel attribut alert(y.a) // 12, ancienne valeur prototype a[12] a[12] x a[8] objet construit objet construit objet construit y y
Incrémentation d’un attribut dans un prototype function Constructeur() {} Constructeur.prototype.a = 12 var x = new Constructeur() vary = new Constructeur() x.a++ // équivalent à x.a = x.a+1 alert(y.a) // 12, ancienne valeur prototype a 12 x objet construit a 13 objet construit y
Héritage de constructeurs prototype constructeur1 construit function Constructeur1() { this.m1 = function() {. . .} } function Constructeur2() { this.m2 = function() {. . .} } Constructeur2.prototype = new Constructeur1() var x = new Constructeur2() x.m1() x.m2() prototype m1 function objet construit 2 m2 x function
Exemple(pas d’arguments) functionTranslation() { this.tPrint = function() { ctx.save() ctx.translate(90, 90)this.print() ctx.restore() }} functionCercle(x,y,r) {this.print = function() { ctx.beginPath() ctx.arc(x,y,r,0,2*Math.PI,true) ctx.stroke() }}. . . . . . Cercle.prototype = new Translation() function execute() {var cercle1 = new Cercle(50,50,15) cercle1.tPrint() cercle1.print()}
Exemple(avec initialisation, « super » en Java) functionTranslation() {this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt)this.print() ctx.restore() }this.initTranslation = function(xt,yt) {this.xt = xtthis.yt = yt }}functionCercle(x,y,r,xt,yt) {this.initTranslation(xt,yt) // super(xt,yt)this.print = function() { ctx.beginPath() ctx.arc(x,y,r,0,2*Math.PI,true) ctx.stroke() }}. . . . . . Cercle.prototype = new Translation() function execute() {var cercle1 = new Cercle(50,50,15,0,0) cercle1.tPrint()var cercle2 = new Cercle(50,55,15,90,90) cercle2.tPrint()}
Appel de super-classe à sub-classeou vice-versa Translation open() close() Translation tPrint() { } this Cercle print() Cercle print() { } signe de l’héritage
Exemple functionTranslation() { this.open = function(xt,yt) { ctx.save()ctx.beginPath() ctx.translate(xt,yt) } this.close = function() { ctx.stroke() ctx.restore() }} functionCercle(x,y,r,xt,yt) {this.print = function() { this.open(xt,yt) ctx.arc(x,y,r,0,2*Math.PI,true) this.close() }}. . . . . . Cercle.prototype = new Translation() function execute() {var cercle1 = new Cercle(50,50,15) cercle1.print() cercle2.print()}
Prototype avec méthodes(première des deux solutions précédentes) function Translation() { } Translation.prototype.initTranslation = function(xt,yt) {this.xt = xtthis.yt = yt}Translation.prototype.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt)this.print() ctx.restore()} . . . . . . function Cercle(x,y,r,xt,yt) {this.x = xthis.y = ythis.r = rthis.initTranslation(xt,yt)}Cercle.prototype = new Translation()Cercle.prototype.print = function() { ctx.beginPath() ctx.arc(this.x,this.y,this.r,0,2*Math.PI,true) ctx.stroke()}
Effet pervers functionGroupe() { this.arr = [ ] } function Cercle(x,y,r) {this.x = x} Cercle.prototype = new Groupe() var c1 = new Cercle(10,20,3) var c2 = new Cercle(20,12,3) c1.arr[0] = 12 c2.arr[0] == 12 // arr est devenu commun !! Solution: initialiser les tableaux et les objets dans la méthode d’initialisation
Exemple des objets graphiques • Cercle, rectangle… • Groupes • Transformations • Sauvetage des dessins • Détection
Hiérarchie de groupes et cerclesavec rotations function execute() {groupeDeBase = new Groupe(0,0,0)groupeDeBase.liste.push(new Cercle(80,120,15,0,0,0))groupeDeBase.liste.push(new Cercle(120,120,15,0,0,0))groupeDeBase.liste.push(new Cercle(120,80,15,0,0,0))groupeDeBase.liste.push(new Cercle(80,80,15,0,0,0))var groupe2 = new Groupe(200,100,0.3)groupeDeBase.liste.push(groupe2)groupe2.liste.push(new Cercle( 220,80,10,0,0,0))groupe2.liste.push(new Cercle( 180,80,10,0,0,0)) groupeDeBase.tPrint()}
Même hiérarchie en SVG <gid='groupeDeBase'stroke='red'transform='rotate(0,0,0)'fill="none"><circleid="circ"cx="80"cy="120"r="15"stroke="red"fill="none"/><circleid="circ"cx="120"cy="120"r="15"stroke="red"fill="none"/><circleid="circ"cx="120"cy="80"r="15"stroke="red"fill="none"/><circleid="circ"cx="80"cy="80"r="15"stroke="red"fill="none" transform='rotate(0,0,0)'/><gid='group1'stroke='red'transform='rotate(30,200,100)'><circleid="circ"cx="220"cy="80"r="15"fill="none"/><circleid="circ"cx="180"cy="80"r="15"fill="none"/></g></g>
Interactions des objets(sans transformations) functionTransformation() {this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt)this.print() ctx.restore() }}functionGroupe(xt,yt) {this.print = function () {for (var i=0; i<this.liste.length; i++) {this.liste[i].tPrint() } }} functionTransformation() {this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt)this.print() ctx.restore() }}functionCercle(x,y,r,xt,yt) {this.print = function() { ctx.beginPath() ctx.arc(x,y,r,0,2*Math.PI,true) ctx.stroke() }}
Groupe Cercle Cercle Cercle Groupe Cercle Cercle Diagramme d’objets // Affichage des groupes this.print = function () {for (var i=0; i<this.liste.length; i++) {this.liste[i].print() } }
Interactions des objets functionTransformation() {this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt)this.print() ctx.restore() }}functionGroupe(xt,yt) {this.print = function () {for (var i=0; i<this.liste.length; i++) {this.liste[i].tPrint() } }} functionTransformation() {this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt)this.print() ctx.restore() }}functionCercle(x,y,r,xt,yt) {this.print = function() { ctx.beginPath() ctx.arc(x,y,r,0,2*Math.PI,true) ctx.stroke() }}
Rotation Groupe Rotation Cercle Rotation Cercle Rotation Cercle Rotation Groupe Rotation Cercle Rotation Cercle Diagramme d’objets // Rotations des groupes et cercles ctx.save()ctx.translate(this.centreX,this.centreY)ctx.rotate(Math.PI/6)ctx.translate(-this.centreX, -this.centreY)this.print()ctx.restore()
Transformation tPrint tTouch Cercle print touch Une hiérarchie de classes FormeGraph print Groupe print touch liste
Sélection (sans transformation) // Curseur xc = event.clientX; yc = event.clientY// Dans le cercle (curseur – centre < r)this.touch = function(xc,yc) {if (Math.sqrt((xc-x)*(xc-x)+(yc-y)*(yc-y))<r) { elSelectionne = thisreturntrue } else {returnfalse }}
Sélection (sans transformation) // Dans le groupethis.touch = function (xc,yc) {for (var i=0; i<this.liste.length;i++) {if (this.liste[i].touch(xc,yc)) {if (this!=groupeDeBase) { elSelectionne = this }returntrue } }returnfalse}
Rotation Groupe Rotation Cercle Cercle Rotation Groupe Sélection avec transformation inverse clientX clientY xc,yc xc,yc transformer-1 transformer-1 transformer-1 xc,yc cercle.touch(xc,yc) // les transformations des coordonnées du curseur doivent être effectuées à // partir de la transformation de base!
Transformation inverse du curseur cos(a) sin(a) 0 -sin(a) cos(a) 0 0 0 1 1 0 y 0 1 x 0 0 1 1 0 -y 0 1 -x 0 0 1 cos(a) sin(a) x -sin(a) cos(a) y 0 0 1 1 0 -y 0 1 -x 0 0 1
Transformation inverse du curseur cos(a) sin(a) x -sin(a) cos(a) y 0 0 1 1 0 -y 0 1 -x 0 0 1 cos(a) sin(a) -x*cos(a)-y*sin(a)+x -sin(a) cos(a) x*sin(a)-y*cos(a)+y 0 0 1 [ [cosA, sinA, -this.xr*cosA-this.yr*sinA+this.xr], [-sinA, cosA, this.xr*sinA-this.yr*cosA+this.yr], [0,0,1] ]
tTouch dans la transformation xc = event.clientX; yc = event.clientY this.tTouch = function(xc,yc) {var cosA = Math.cos(this.angle)var sinA = Math.sin(this.angle)var xy= multV([[cosA, sinA, -this.xr*cosA-this.yr*sinA+this.xr],[-sinA, cosA, this.xr*sinA-this.yr*cosA+this.yr], [0,0,1] ], [xc,yc,1])returnthis.touch(xy[0],xy[1])}
Sauvetage • Créer un arbre sans les méthodes • Sauver l’arbre au moyen de JSON dans un fichier Restauration • Lire le fichier et retransformer le contenu en arbre au moyen de JSON • Recréer l’arbre avec les méthodes en recréant les objets (new)
Création d’objets pour la sauvegarde(constants, sans méthodes) // Cerclethis.save = function() {// objet avec les paramètres d’un cerclereturn {x:x, y:y, r:r, xr:xr, yr:yr, angle:angle, strokeStyle:this.strokeStyle}} // Groupethis.save = function () {// un groupe contient une liste + qq paramètres var g = { liste: [], xr:xr, yr:yr, angle:angle}for (var i=0; i<this.liste.length;i++) { g.liste.push(this.liste[i].save()) }return g}
Restauration à partir des objets JSON //Groupe this.restore = function(o) {//o, el objets obtenu par JSONfor (var i=0; i<o.liste.length;i++) {//this, groupe en constructionvar el = o.liste[i]if (el.liste) {// c'est un groupevar g = new Groupe(el.xr, el.yr, el.angle)this.liste.push(g) g.restore(el) } elseif (el.r) {// c'est un cercle1var c = new Cercle(el.x, el.y, el.r, el.xr, el.yr, el.angle) c.strokeStyle = el.strokeStylethis.liste.push(c) } }// 1 on ne pas mettre cette instruction dans Cercle, } // car il faut le créer avant d’appeler ses méthodes !
Transformation JSON dessin groupeDeBase racine JSON o méthodes el this.liste.push( new Groupe(el…) ) new Cercle(el…) méthodes méthodes
Objets JSON function save(filename) {var dessin = groupeDeBase.save() File.write(filename, JSON.stringify(dessin))} function restore(filename) {var dessin = JSON.parse(File.read(filename)) groupeDeBase = new Groupe(0,0,0) groupeDeBase.restore(dessin)} http://lti.epfl.ch/Livre/Solutions/Ex_8.7.1c.html