Tout ce qui concerne le logiciel E-anim
 
AccueilPortailFAQS'enregistrerConnexion

Partagez | 
 

 Héritage en Javascript

Voir le sujet précédent Voir le sujet suivant Aller en bas 
AuteurMessage
Admin
Administrateur
Administrateur
avatar

Nombre de messages : 18431
Localisation : Toulouse
Date d'inscription : 11/12/2005

Message Sujet: Héritage en Javascript   Lun 10 Mar 2014, 04:12

Pour l'héritage en javascript, il est recommandé d'utiliser les prototypes. je ne les utilise pas.
Pourquoi ne pas utiliser les prototypes ? Je préfère profiter de l'étendue des possibilités 'basiques' de Javascript.  C'est un langage extrêmement bien étudié, dont la 'logique' permet d'éviter l'usage de prothèse chimérique.

Ces script imposent des règles simples :
Règles a écrit:
1 - Ce langage intègre l'héritage non modifiable durant l'exécution (comme le C++, le java)
2 - Il existe 2 contextes pour les fonction : fonction de classe et fonction d'occurence (comme en C++ et en Java)
Note : inutile de de préoccuper de la différence des
3 - Ce langage intègre les pointeurs de fonction.
Toutes les fonctions sont placée dans une variable, ces variables se comportent comme des pointeurs de fonction, donc modifiables durant le traitement.
4 - la modification d'une variable de fonction n'affecte qu'une seule occurence d'objet.

Ces scripts sont compatibles avec les règles élémentaires du Javascript.
Après test, la vitesse d'exécution d'appel de fonction correspond aux autres mécanismes les plus rapides.

Pour reproduire l'héritage j'utilise 3 mécanismes :
A - Pour incorporer les attributs des parents dans la structure de l'objet en construction : utiliser la fonction 'call' du constructeur du parent (c'est classique)
B - Pour la reconnaissance de type : créer un "attribut_de_type" dans chaque classe
Ensuite l'instruction 'if(typeOf..)' sera remplacée par : if(this.attribut_de_type!=null)
C - Pour les accès aux parents - cf. 'super' - nous plaçons la fonction-parent dans un attribut 'super_'
Plus précisément, placer la fonction dans un attribut qui comporte le même nom que cette fonction, ce nom est précédé de 'super_'
Exemple : this.getName devient this.super_getName.

Et enfin, pour conserver une rapidité d'exécution et ne pas dupliquer les fonctions, elles sont définies en static
D - définition de fonctions en static. Exemple : MaClasse.maFonction_S = function(){}
Elles sont ensuite placées dans l'objet lors de la construction.
Exemple : this.maFonction = MaClasse.maFonction_S;

Nous pouvons aisément imaginer un langage simple traduit en Javascript par un préprocesseur qui prendrait en charge la construction de ces fonctionnalités.
__________________________________________________________________

Voyons comment réaliser ces fonctionnalités ?
__________________________________________________________________

A - Appel du constructeur parent à l'aide de la fonction 'call'
C'est classique
Voir : le cours de programmez.com paragraphe 1.1

Mais, contrairement à Développez.com, je recommande cette construction sans prototype, comme expliqué ci-dessus, en introduction.

B - L'attribut de classe.
C'est un attribut, donc inscrit après 'this.' qui existe uniquement dans la classe indiquée.
Exemple : pour la classe 'Animal', nous créerons : 'this.class_Animal'

Pourquoi créer cet 'attribut-de-classe' ?
Pour reconnaitre le type d'un objet. dans d'autres langages cette vérification de type peut s'écrire 'typeOf', 'instanceof'... mais dans notre méthode, nous ferons une simple égalité.
Il est impératif que cet attribut-de-classe ne soit présent que dans la classe qui lui est associée.

Voici une construction d'objet.
Code:
function Animal(){
    this.class_Animal = true;
}
var animal = new Animal();
if(animal.class_Animal){/*TODO*/};

Puisque nous utilisons le constructeur 'Parent.call(this)', les 'attributs_de_classe' des parent sera collectés lors du passage dans le constructeur du parent.
Voici une construction d'objet. voir test
Code:
function Animal(){
    this.class_Animal = true;
}
function Chien(){
    Animal.call(this);
    this.class_Chien = true;
}
var chien = new Chien();
if(chien.class_Animal){/*TODO*/}; // cette comparaison sera vraie
         // puisque 'Chien' aura collecté 'class_Animal' lors de l'appel Animal.call(this);

Important : il est à noter que nous avons utilisé l'attribut-de-classe comme un simple flag, mais rien n'empêche de lui affecter une valeur, une fonction ou même un objet complexe.
Cela peut ouvrir des perspectives inattendues.

C - les accès aux fonctions parents, à l'aide de l'instruction 'super'
Rappel : lors de la construction d'un objet, les fonctions des parents sont écrasées par les fonctions des fils. Comment simuler l'instruction 'super' ?
Réponse : en conservant la fonction du parent  Cool 
Comment ?
1 - Dans le constructeur, après avoir collecté les fonctions des parents, nous déplaçons la fonction du parent dans la variable-de-type.
Exemple : this.class_MySuper.myFonction = this.myFunction
Ainsi l'attribut de cette fonction est libre et peut recevoir la fonction du fils.

2 - l'appel de la fonction super
- l'appel est en fait un 'call' pour conserver l'appelant 'this'
- l'appel de la fonction parent ne débute plus par 'super.' -> mais par la variable de class du parent qui comporte cette fonction 'class_MySuper.'

Avec une programmation de bucheron,  nous préparons toutes les fonctions pour être appelé par "super".
Il suffit d'ajouter la fonction dans la variable-de-type. Exemple : this.class_Animal.toString = Animal.toString_S;
Mais vous pouvez créer une ptite routine qui construira ces fonctions super, dans ce cas vous ne construirez que les fonctions 'super' réellement requises.

Exemple : (voir test)
Code:
//________ Classe parent ________
function Truc(){
   this.class_Truc = [];                // Initialise la variable de classe
                                        // Prépare la fonction 'super'
   this.class_Truc.toString = Truc.toString_S;
   this.toString = Truc.toString_S;     // La fonction parent est placé dans l'objet
}
Truc.toString_S = function(){return "Tiens un truc ! ";}
//________ Classe parent ________
function Animal(){
   Truc.call(this);                      // Construction du parent  
   this.class_Animal = [];               // Initialisation d la variable de classe
                                         // Prépare la fonction 'super'
   this.class_Animal.toString = Animal.toString_S;
   this.toString = Animal.toString_S;    // La fonction parent est placé dans l'objet
}
Animal.toString_S = function(){return this.class_Truc.toString.call(this)+"c'est un animal";}

//________ Classe héritière ________
function Chien(){
   Animal.call(this);                      // Construction du parent
   this.class_Chien = [];                  // Initialisation d la variable de classe
                                           // Prépare la fonction 'super'
   this.class_Chien.toString = Chien.toString_S;
   this.toString = Chien.toString_S;       // La fonction du fils receuille celle du Chien
}
Chien.toString_S=function(){
    return this.class_Animal.toString.call(this)+", est plus précisément un chien";
}

var chien = new Chien();
alert(chien.toString()); // Affiche "c'est un animal, est plus précisément un chien"
        // puisque 'Chien' aura collecté 'class_Animal' lors de l'appel Animal.call(this);

D - optimisation vitesse et espace : les fonction sont décrites en static, elle est ensuite placée dans un attribut d'occurence :
Pour avoir un comportement de type static - la fonction est écrite une seule fois pour toute la classe :
- la fonction doit être décrite hors du corp de la classe.
- elle doit être précédé du nom de la class : MyClass.myFunction_S = function(...){...}
note : ajoutons "_S' ('S' comme static) à la fin du nom pour indiquer qu'elle est static.

Pour placer une fonction 'static' dans un attribut-d'occurence, une simple affectation (signe égal classique) suffit.
Exemple : this.myFunction = MyClass.myFunction_S;

Exemple :
Code:
//________ Classe parent ________
Function Animal(){
 this.toString = MyClass.toString_S;
}
Animal_S.toString_S = function(){return "c'est un animal";}

_________________
.


Dernière édition par Admin le Sam 15 Mar 2014, 02:10, édité 2 fois
Revenir en haut Aller en bas
http://www.e-anim.com
Admin
Administrateur
Administrateur
avatar

Nombre de messages : 18431
Localisation : Toulouse
Date d'inscription : 11/12/2005

Message Sujet: Re: Héritage en Javascript   Sam 15 Mar 2014, 02:45

Le mécanisme de création de variable-de-type et d'accès aux fonctions 'super' peut être automatisé :
Une fonction crée la variable-de-type puis duplique toutes les fonctions de la classe dans cette variable de type.

A venir :
- il sera possible de filtrer les copies dans la variable-de-type pour ne conserver que les fonctions
- nous pourrions aussi combler les trous dans le classes qui ne possèdent pas les fonctions de parents.
(mais ceci n'est possible que pour les classes dont un seul parent possède la fonction manquante (sinon un conflit peut compliquer l'affaire)


Voir test : cliquez ici
Code:
//______ construction automatique des 'super' ______
function sysPh(){}
sysPh.classVar = function(varClassName){
    this[varClassName] = [];
    this[varClassName].isVarClass = true;
    var c;
    for (var p in this) {
       if (!(c = this[p]).isVarClass) this[varClassName][p] = c;
    }
}

//________ Classe parent ________
function Truc(){
   this.toString = Truc.toString_S;     // La fonction parent est placé dans l'objet
   sysPh.classVar.call(this,"class_Truc");
}
Truc.toString_S = function(){return "Tiens un truc ! ";}
//________ Classe parent ________
function Animal(){
   Truc.call(this);                      // Construction du parent  
   this.toString = Animal.toString_S;    // La fonction parent est placé dans l'objet
   sysPh.classVar.call(this,"class_Animal");
}
Animal.toString_S = function(){return this.class_Truc.toString.call(this)+"c'est un animal";}

//________ Classe héritière ________
function Chien(){
   Animal.call(this);                      // Construction du parent
   this.toString = Chien.toString_S;       // La fonction du fils receuille celle du Chien
   sysPh.classVar.call(this,"class_Chien");
  
   var message = "";
    
   for (var p in this["class_Chien"]) {
      message += p+'\n';
   }
   alert(message);
    
}
Chien.toString_S=function(){
    return this.class_Animal.toString.call(this)+", est plus précisément un chien";
}


//_____________ Test _______________
var chien = new Chien();
alert(chien.toString()); // Affiche "c'est un animal, est plus précisément un chien"
        // puisque 'Chien' aura collecté 'class_Animal' lors de l'appel Animal.call(this);

_________________
.


Dernière édition par Admin le Sam 15 Mar 2014, 03:01, édité 1 fois
Revenir en haut Aller en bas
http://www.e-anim.com
 
Héritage en Javascript
Voir le sujet précédent Voir le sujet suivant Revenir en haut 
Page 1 sur 1
 Sujets similaires
-
» [Fermé] application javascript
» [RESOLU] une action en sortant d'un bouton (type onmouseout)
» Compteur à rebours
» INTRO d'un blog overblog en flash
» Résolu => Comment faire disparaitre la souris?

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
E-anim :: Autres :: Autre langages - java, javascript, php...-
Sauter vers: