IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Programmation orientée objet par prototype avec jQuery


précédentsommairesuivant

VIII. Mise en œuvre de l'héritage simple

Squelette d'une classe mère et de sa classe fille
Sélectionnez
try {
  var FuncClassMere = $.dvjhClass._create({
    _builder: function(){
        // le constructeur de la fonction classe mère
    },
    toString: function(){
        return "FuncClassMere : ";
    }
  });

  var FuncClassFille = $.dvjhClass._create(FuncClassMere, {
    _builder: function(){
        this._base(arguments.callee, FuncClassMere, arguments);
        
        // le constructeur de la fonction classe fille
    },
    toString: function(){
        return "FuncClassFille : ";
    }
  });
}
catch(err){
  alert(err);
}

Pour la « fonction classe » fille, le premier argument de $.dvjhClass._create() devient la « fonction classe » poopj mère et le corpus de la « fonction classe » fille devient le second argument de la méthode _create().

La première ligne du constructeur d'une « fonction classe » fille doit toujours être this._base(arguments.callee, FuncClassMere, arguments).

L'insertion de FuncClassMere comme premier argument de la méthode _create(), permet l'héritage du prototype de la « fonction classe » mère.

En utilisant « arguments.callee », on permet à une fonction anonyme de se référencer elle-même, on peut ainsi déclencher l'initialisation récursive des « fonctions classes » mères.

L'existence de this._base() est une contrainte acceptable en regard des avantages qu'il procure. J'ai essayé d'autres solutions, mais elles étaient toutes plus complexes à mettre en œuvre au niveau de l'objet $.dvjhClass et plus coûteuses pour l'objet instancié et son prototype.

Mise en oeuvre de l'héritage simple (poopj8.html)
Sélectionnez
try {
  var Personne = $.dvjhClass._create({
    _builder: function(prenom, nom){
        this.prenom = prenom;
        this.nom = nom;
    },
    toString: function(){
        return "Personne : ";
    }
  });

  var Etudiant = $.dvjhClass._create(Personne, {
    _builder: function(prenom, nom, numero){
        this._base(arguments.callee, Personne, arguments);
        this.numero = numero;
    },
    toString: function(){
        return "Etudiant : ";
    }
  });

  var Chanteur = $.dvjhClass._create(Personne, {
    _builder: function(prenom, nom, voix){
        this._base(arguments.callee, Personne, arguments);
        this.voix = voix;
    },
    toString: function(){
        return "Chanteur : ";
    }
  });

  var Interne = $.dvjhClass._create(Etudiant, {
    _builder: function(prenom, nom, numero, chambre){
        this._base(arguments.callee, Etudiant, arguments);
        this.chambre = chambre;
    },
    toString: function(){
        return "Interne : ";
    }
  });

  var Tenor = $.dvjhClass._create(Chanteur, {
    _builder: function(prenom, nom, voix){
        this._base(arguments.callee, Chanteur, arguments);
        this.ton = "grave";
    },
    toString: function(){
        return "Tenor : ";
    }
  });

  /*
   * L'ordre des arguments du constructeur dans une fonction classe
   * fille doit bien entendu être rigoureusement identique à celui
   * de la fonction classe mère sous peine d'erreurs dans 
   * l'initialisation des attributs de la classe mère.
   */
  var moi = new Personne("Daniel", "Hagnoul");
  var etudiant = new Etudiant("Pierre", "Dupond", 111);
  var chanteur = new Chanteur("Henri", "Latour", "soprano");
  var interne = new Interne("Jaques", "Lemaitre", 111, "royale");
  var tenor = new Tenor("Gustave", "Lefort", "tenor");
            
  console.log(moi);
  console.log(etudiant);
  console.log(chanteur);
  console.log(interne);
  console.log(tenor);
}
catch(err){
  alert(err);
}

La technique d'héritage mise en œuvre ne permet pas le polymorphisme (objX instanceof objY), mais c'est la plus appropriée dans la plupart des cas. Si le polymorphisme et l'héritage multiple vous manquent, le tutoriel de Thierry Templier décrit d'autres techniques d'héritage.

L'objet _super stocke une copie des méthodes du prototype de la « fonction classe » mère.

Appel d'une méthode de la fonction classe mère (poopj9.html)
Sélectionnez
try {
  var Personne = $.dvjhClass._create({
    _builder: function(prenom, nom){
        this.prenom = prenom || "";
        this.nom = nom || "";
        this.adresse = "Belgique";
    },
    getAdresse: function(){
        return "J'habite en " + this.adresse;
    },
    toString: function(){
        return "Personne";
    }
  });

  var Etudiant = $.dvjhClass._create(Personne, {
    _builder: function(prenom, nom, numero){
        this._base(arguments.callee, Personne, arguments);
        this.numero = numero || -1;
    },
    getAdresse: function(){
        /*
         * Les méthodes de l'objet _super doivent toujours s'exécuter
         * dans le contexte de l'objet appelant.
         *
         * On peut utiliser call(this, param1, param2, etc.) 
         * ou apply(this, arguments)
         */
        return this._super.getAdresse.call(this) + 
               ". Cette adresse est valable !\n";
    },
    toString: function(){
        return "Etudiant";
    }
  });

  var dvjh = new Personne("Daniel", "Hagnoul");
  console.log(dvjh.getAdresse());

  var pierre = new Etudiant("Pierre", "Dubois", 427);
  console.log(pierre.getAdresse());

  console.log(dvjh, pierre);

  console.log(pierre._super.getAdresse.call(pierre));
}
catch(err){
  alert(err);
}

La méthode toString() et l'objet _super peuvent être utilisés dans le code d'une « fonction classe » ou par l'objet instancié.

On peut redéfinir les options _auteur, _copyright et _version, mais on ne doit pas toucher à l'option _abstract. On peut créer et utiliser d'autres options.

Toucher à _create(), _builder() ou _base() ne conduira qu'à la catastrophe.


précédentsommairesuivant