1Faculté I&C, Claude Petitpierre, André Maurer
Héritage par prototype
• Héritage d’attributs ou de méthodes
• Héritage de constructeurs
2Faculté I&C, Claude Petitpierre, André Maurer
Héritage de méthodesfunction Constructeur() { this.m1 = function () { . . . } }
Constructeur.prototype.m2 = function () { . . . }
var x = new Constructeur()
var y = new Constructeur()
x.m2()
y.m2()
objet construitthis.m1
prototype
m1()
m2()
Le lien n’est pas directement accessible par le programmeUn sous-objet (attribut) prototype est automatiquement créé dans chaque fonction
x objet construitthis.m1
y
m1()
3Faculté I&C, Claude Petitpierre, André Maurer
Héritage de méthodesfunction Constructeur() { this.m1 = function () { . . . }}
Constructeur.prototype.m2 = function () { . . . }
var x = new Constructeur()
Constructeur.prototype.m3 = function () { . . . }
// après la créationx.m1()
x.m2()
x.m3()
Constructeurthis.m1
prototype
m1()
m3()
m2()
4Faculté I&C, Claude Petitpierre, André Maurer
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 )
objet construitthis.a
prototypebc
12
14
13
x
5Faculté I&C, Claude Petitpierre, André Maurer
Ré-écriture des attributs !
objet construitthis.a
prototypea
14
13
function Constructeur() { }
Constructeur.prototype.a = 13
var x = new Constructeur()var y = new Constructeur()
alert(x.a) // 13x.a = 14alert(x.a) // 14alert(y.a) // 13
x.a = 14
Chaque objet lit la valeur initiale, jusqu’à ce qu’il la change. Chaque objet a sa propre valeur.
x
6Faculté I&C, Claude Petitpierre, André Maurer
Tableaux ou objet dans les prototypes !
Constructeur
prototypea [13]
function Constructeur() { }
Constructeur.prototype.a = [ ]
var x = new Constructeur()
var y = new Constructeur()
x.a[0] = 13
alert( y.a[0] ) // aussi 13
Les tableaux et les objets sont donc mis en commun
xobjet construit
y
7Faculté I&C, Claude Petitpierre, André Maurer
Création d’un nouveau tableau ou objet dans un prototype
objet construit
prototype a[12]
function Constructeur() { }
Constructeur.prototype.a = [12]
var x = new Constructeur()
var y = new Constructeur()
x.a = [8] // nouvel attribut
alert(y.a) // 12, ancienne valeur
x
objet construity
a[8]
a[12]
objet construity
8Faculté I&C, Claude Petitpierre, André Maurer
Incrémentation d’un attribut dans un prototype
objet construita
prototypea
function Constructeur() { }
Constructeur.prototype.a = 12
var x = new Constructeur()
var y = new Constructeur()
x.a++ // équivalent à x.a = x.a+1
alert(y.a) // 12, ancienne valeur
13
12
objet construit
y
x
9Faculté I&C, Claude Petitpierre, André Maurer
Héritage de constructeurs
prototype
function Constructeur1() {
this.m1 = function() {. . .}
}
function Constructeur2() {
this.m2 = function() {. . .}
}
Constructeur2.prototype =
new Constructeur1()
var x = new Constructeur2()
x.m1()
x.m2()
objet construit 2m2
prototypem1
xfunction
constructeur1 construit
function
10Faculté I&C, Claude Petitpierre, André Maurer
Exemple (pas d’arguments)
function Translation() { this.tPrint = function() { ctx.save() ctx.translate(90, 90) this.print() ctx.restore() }}
function Cercle(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()}
11Faculté I&C, Claude Petitpierre, André Maurer
Exemple(avec initialisation,
« super » en Java)
function Translation() { this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt) this.print() ctx.restore() } this.initTranslation = function(xt,yt) { this.xt = xt this.yt = yt }}function Cercle(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()}
12Faculté I&C, Claude Petitpierre, André Maurer
Appel de super-classe à sub-classeou vice-versa
Translation
tPrint() {
}
Cercle
print()
Translation
open()
close()
Cercle
print() {
}
this
signe de l’héritage
13Faculté I&C, Claude Petitpierre, André Maurer
Exemple
function Translation() { this.open = function(xt,yt) { ctx.save() ctx.beginPath() ctx.translate(xt,yt) } this.close = function() { ctx.stroke() ctx.restore() }}function Cercle(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()}
14Faculté I&C, Claude Petitpierre, André Maurer
Prototype avec méthodes(première des deux solutions précédentes)
function Translation() { }
Translation.prototype.initTranslation = function(xt,yt) { this.xt = xt this.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 = x this.y = y this.r = r this.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()}
15Faculté I&C, Claude Petitpierre, André Maurer
Effet perversfunction Groupe() { 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] = 12c2.arr[0] == 12 // arr est devenu commun !!
Solution: initialiser les tableaux et les objets dans la méthode d’initialisation
16Faculté I&C, Claude Petitpierre, André Maurer
Exemple des objets graphiques
• Cercle, rectangle…
• Groupes
• Transformations
• Sauvetage des dessins
• Détection
17Faculté I&C, Claude Petitpierre, André Maurer
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()}
18Faculté I&C, Claude Petitpierre, André Maurer
Même hiérarchie en SVG<g id='groupeDeBase' stroke='red' transform='rotate(0,0,0)' fill="none">
<circle id="circ" cx="80" cy="120" r="15" stroke="red" fill="none"/>
<circle id="circ" cx="120" cy="120" r="15" stroke="red" fill="none"/>
<circle id="circ" cx="120" cy="80" r="15" stroke="red" fill="none"/>
<circle id="circ" cx="80" cy="80" r="15" stroke="red" fill="none"
transform='rotate(0,0,0)' />
<g id='group1' stroke='red' transform='rotate(30,200,100)'>
<circle id="circ" cx="220" cy="80" r="15" fill="none"/>
<circle id="circ" cx="180" cy="80" r="15" fill="none"/>
</g>
</g>
19Faculté I&C, Claude Petitpierre, André Maurer
function Transformation() { this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt) this.print() ctx.restore() }}function Cercle(x,y,r,xt,yt) { this.print = function() { ctx.beginPath() ctx.arc(x,y,r,0,2*Math.PI,true) ctx.stroke() }}
Interactions des objets(sans transformations)
function Transformation() { this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt) this.print() ctx.restore() }}function Groupe(xt,yt) { this.print = function () { for (var i=0; i<this.liste.length; i++) { this.liste[i].tPrint() } }}
20Faculté I&C, Claude Petitpierre, André Maurer
Diagramme d’objets
Groupe
Cercle
Cercle
Cercle
Groupe
Cercle
Cercle
// Affichage des groupesthis.print = function () { for (var i=0; i<this.liste.length; i++) { this.liste[i].print() } }
21Faculté I&C, Claude Petitpierre, André Maurer
function Transformation() { this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt) this.print() ctx.restore() }}function Cercle(x,y,r,xt,yt) { this.print = function() { ctx.beginPath() ctx.arc(x,y,r,0,2*Math.PI,true) ctx.stroke() }}
Interactions des objets
function Transformation() { this.tPrint = function() { ctx.save() ctx.translate(this.xt,this.yt) this.print() ctx.restore() }}function Groupe(xt,yt) { this.print = function () { for (var i=0; i<this.liste.length; i++) { this.liste[i].tPrint() } }}
22Faculté I&C, Claude Petitpierre, André Maurer
Diagramme d’objets
RotationGroupe
RotationCercle
RotationCercle
RotationCercle
RotationGroupe
RotationCercle
RotationCercle
// Rotations des groupes et cerclesctx.save()ctx.translate(this.centreX, this.centreY)ctx.rotate(Math.PI/6)ctx.translate(-this.centreX, -this.centreY)this.print()ctx.restore()
23Faculté I&C, Claude Petitpierre, André Maurer
Une hiérarchie
de classesTransformationtPrinttTouch
FormeGraphprint
Groupeprinttouch
liste
Cercleprinttouch
24Faculté I&C, Claude Petitpierre, André Maurer
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 = this return true } else { return false }}
25Faculté I&C, Claude Petitpierre, André Maurer
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 } return true } } return false}
26Faculté I&C, Claude Petitpierre, André Maurer
Sélection avec transformation inverse
RotationGroupe
RotationCercle
clientXclientY xc,yc
xc,ycxc,yctransformer-1 transformer-1 transformer-1
cercle.touch(xc,yc)Cercle
// les transformations des coordonnées du curseur doivent être effectuées à// partir de la transformation de base!
RotationGroupe
27Faculté I&C, Claude Petitpierre, André Maurer
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
28Faculté I&C, Claude Petitpierre, André Maurer
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
[ [cosA, sinA, -this.xr*cosA-this.yr*sinA+this.xr], [-sinA, cosA, this.xr*sinA-this.yr*cosA+this.yr], [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
29Faculté I&C, Claude Petitpierre, André Maurer
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]) return this.touch(xy[0],xy[1])}
30Faculté I&C, Claude Petitpierre, André Maurer
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)
31Faculté I&C, Claude Petitpierre, André Maurer
Création d’objets pour la sauvegarde(constants, sans méthodes)
// Cerclethis.save = function() { // objet avec les paramètres d’un cercle return {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}
32Faculté I&C, Claude Petitpierre, André Maurer
Restauration à partir des objets JSON// Groupe this.restore = function(o) { // o, el objets obtenu par JSON for (var i=0; i<o.liste.length;i++) { // this, groupe en construction var el = o.liste[i] if (el.liste) { // c'est un groupe var g = new Groupe(el.xr, el.yr, el.angle) this.liste.push(g) g.restore(el) } else if (el.r) { // c'est un cercle1
var c = new Cercle(el.x, el.y, el.r, el.xr, el.yr, el.angle) c.strokeStyle = el.strokeStyle this.liste.push(c) } } // 1 on ne pas mettre cette instruction dans Cercle, } // car il faut le créer avant d’appeler ses méthodes !
33Faculté I&C, Claude Petitpierre, André Maurer
Transformation JSON dessin
groupeDeBase
méthodes
méthodes méthodes
racine JSON
el this.liste.push( new Groupe(el…) ) new Cercle(el…)
o
34Faculté I&C, Claude Petitpierre, André Maurer
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