Programmation objet héritage JQuery JavaScript OOP

    JavaScript n'utilise pas la notion de  classe pour la création d'objets . A la place les objets peuvent être crées  par  différentes manières notamment par constructeur  qui crée l objet et initialise certain propriétés .
Le constructeur est une fonction qui possède une propriété "prototype"   utilisée   pour l héritage basé sur le prototype et pour partager les propriétés entre différentes  instances  . Les instances d'objets sont alors créées par le mot clef "new" suivi du constructeur ex : new String("bonjour").Ainsi chaque instance partage une référence avec le prototype de son constructeur .

Voyons maintenant pour examiner   quelques exemples de création d'objet en JavaScript . On utilisera la classe "personne" pour questions pratiques.

Création par constructeur

on déclare une fonction dans laquelle on implémente les méthodes et propriétés ce qui rappel les classes dans d'autres langages orientes objet tels que C++, Java, C#...

function Personne( nom, sexe){
     this.DateNaissance=new Date();
     this.nom=nom || "Dupont";
     this.sexe=sexe;
     this.renommer=function(nom){
                                  if(nom)this.nom=nom;
                                 };
                                                                             
}
On a déclaré le constructeur , on ajoute quelques méthodes par le prototype ; methodes qui seront partagées par toutes les instances .

Personne.prototype.quelAge=function(){
                            var ms=new Date()-this.DateNaissance;
                            var ans=ms/1000/60*60*24/365.25;  
                             return Math.floor(ans)+1+" an";
                           }

 Maintenant pour créer une instance on procède ainsi  :

var jaques=new Personne("Jacques","Masculin");
//affiche l age de Jacques.
alert(jaques.quelAge());

ce qui affiche 1 an  , normal Jacques vient de naître  il a moins d'un an . on va pas dire zéro ...

Création par  notation littérale 

cette fois au lieu de passer par le constructeur on instancie directement un objet par une instance de l objet prédéfinie Object :
var jaques=new Object();
     //on attache dynamiquement les propriétés a l'instance
     jaques.nom="Jacques";
  jaques.sexe="Masculin";
  jaques.DateNaissance=new Date();
     jaques.quelAge=function(){
                            var ms=new Date()-this.DateNaissance;
                            var ans=ms/1000/60*60*24/365.25;  
                             return Math.floor(ans)+1+" an";
                           }

alert(jaques.quelAge());

de même que précédemment  affiche 1 an.


Une autre façon de créer un objet est d'utiliser la représentation JSON    soit :

 var jaques={};
     //on attache dynamiquement les propriétés a l'instance
     jaques.nom="Jacques";
  jaques.sexe="Masculin";
  jaques.DateNaissance=new Date();
     jaques.quelAge=function(){
                            var ms=new Date()-this.DateNaissance;
                            var ans=ms/1000/60*60*24/365.25;  
                             return Math.floor(ans)+1+" an";
                           };

alert(jaques.quelAge());

ce qui  affiche 1 an.

ou directement :

var jaques={
     //on attache dynamiquement les propriétés a l'instance
     nom :"Jacques",
  sexe "Masculin",
  DateNaissance new Date(),
     quelAge function(){
                            var ms=new Date()-this.DateNaissance;
                            var ans=ms/1000/60*60*24/365.25;  
                             return Math.floor(ans)+1+" an";
                           }

};
//et on ajoute une propriétés 
jaques.renommer=function(nom){
                 if(nom)this.nom=nom;
                          };


alert(jaques.quelAge());

  Affiche a nouveau  1 an.


On vient de voir les Différentes manières de création d'objet et JavaScript  a présent on s’intéressera au autre notions de la programmation oriente objet POO en JavaScript et on fera une analogie avec les autre langages objet

Variables et accesseurs

En utilisant la création par constructeur qui ressemble a la notion de classe dans Java, C# :
On peut distinguer différents accesseur pour les attributs d un objet
privé, public , public privilégie, et public statique 

pour illustration reprenons l exemple de  "Personne"



function Personne( nom, sexe){
     //propriétés privées 
     var celibataire =true;

     //propriétés public privilégiées 

     this.DateNaissance=new Date();
     this.nom=nom|| "Dupont";
     this.sexe=sexe;

      //incrémentation d'une propriétés public statique
     this.constructor.nombreDeNaissance++;

     //méthodes public privilégiées
     this.renommer=function(nom){
                                  if(nom)this.nom=nom;
                                 };
     this.seMarie= function(){
                                   celibataire =false;
                               };
     thisestMarie=function(){
                               return celibataire?"Non":"Oui" ;
                              }
     this.divorce = function(){
                                   celibataire=true;
                               };
     this.mange= function(){
                               alert("envoies la mayonnaise ");
                               };
     this.quelAge= function(){
                          return calculerAge(this.DateNaissance);
                          };
    
      //méthodes  privées

      function calculerAge(date){
                            var ms=new Date()-date;
                            var ans=ms/1000/60*60*24/365.25;  
                             return Math.floor(ans)+1+" an";
                      };

                           
                                                                        
}
  //propriétés public statique
Personne.nombreDeNaissance=0;

  //méthodes  public  



Personne.prototype.mange=function(){
                             alert("...pas faim !! ");
                           }; 



var jaques=new Personne("Jacques","Masculin");
alert(jaques.quelAge()); //affiche 1 an 
//utilise la méthode privée pour calculer l age 
alert(jaques.estMarie()); //affiche  Nom 
//affiche la valeur de propriété privée celibataire 
 jaques.seMarie() ; 
//modifie la valeur de propriété privée celibataire  
alert(jaques.estMarie()); //affiche  Oui
//affiche a nouveau la valeur de propriété privée celibataire 

jaques.divorce () ; 
 //modifie la valeur de propriété privée celibataire  
alert(jaques.estMarie()); //affiche  Nom ,(il vient de divorcer)

//affiche a nouveau la valeur de propriété privée celibataire

alert(Personne.nombreDeNaissance); //affiche 1 (celle de Jacques)
//affiche   la valeur de propriété statique nombreDeNaissance
jaques.mange() //affiche envoies la mayonnaise
///on constate que c est la méthode public privilégié qui s’exécute non la méthode public définie dans le prototype 

Ici on ajoute a jacques des propriétés dynamiquement :

jaques.celibataire="depuis peu"
alert(jaques.estMarie()); //affiche  Nom
//affiche toujours la valeur de propriété privée celibataire
var marie=new Personne("Marie","féminin");
alert(jaques.celibataire);//affiche  depuis peu
alert(marie.celibataire);   //affiche undefined


jaques possède deux propriétés qui portent le même nom "celibataire" une public  et l autre privée .
par contre marie ne possède que la propriété privée du même nom celle du constructeur  


Héritage , polymorphisme extension d'objet  

allons droit au but et gardons en tète la "classe" Personne définie précédemment a la quelle on rajoutera quelles  attributs soit :

Personne.prototype.toString=function (){
                     return "[Personne]:"+this.nom;
}

Personne.prototype.travailler=function (){
                     return "[Personne]: que c'est dur";
}

Maintenant on veut créer une classe Salarie qui dérive de  Personne ?

   On pourrait directement créer une instance de la Personne et on rajoute les propriétés spécifiques au salarié Mais dans notre cas on veut rester avec les constructeurs et prototype  la première idée serait d écrire ce ci  :


 Salarie .prototype=new Personne();
    //assigner toutes les propriétés d'une instance de 
    //personne au prototype de nouvelle instance Salarie  

function Salarie (nom ,profession){
      
       
       Personne.call(this,nom);
       //on exécute le constructeur de la classe Personne dans le
       // contexte de Salarie
  
       this.salaire=1000;
       this.profession=profession;
      //propriétés spécifiques au Salarie 
}

Voyons ce que ça donne en vrai :

var marie=new Salarie ("Marie","Comptable");

alert(marie );//appel toString affiche  [Personne]:Marie
alert(marie.profession);   //affiche Comptable


 marie.mange() ;//affiche  envoies la mayonnaise
 alert(marie.travailler());   //"[Personne]: que c'est dur";


C'est déjà pas mal !. Mais si on veut  faire en sort que la surcharge puisse fonctionner ? on le constate bien le toString affiche toujours [Personne]:Marie si on veut plutôt  [Salarie ]:Marie
dans ce cas faudra réexaminer le toString de la classe de base  ainsi :


Personne.prototype.toString=function (){
               return "["+this.constructor.name+"]"+this.nom;
}

Personne.prototype.travailler=function (){
                     return "["+this.constructor.name+"]: que c'est dur";
}


et on précise a la classe Salarie  que le constructeur associé a son prototype est bien Salarie

ce qui donne :
Salarie .prototype=new Personne();
Salarie.prototype.constructor=Salarie ;


    //assigner toutes les propriétés d'une instance de 
    //personne au prototype de nouvelle instance Salarie
    //associe Salarie au constructeur de son prototype   

function Salarie (nom ,profession){
           
       Personne.call(this,nom);
       //on exécute le constructeur de la classe Personne dans le
       // contexte de Salarie
       this.salaire=1000;
       this.profession=profession;
      //propriétés spécifiques au Salarie 
}



var marie=new Salarie ("Marie","Comptable");

alert(marie );//appel toString affiche  [Salarie ]:Marie
alert(marie.profession);   //affiche Comptable


alert(marie.travailler());   //"[Salarie ]: que c'est dur";


Et voilà ! ca fonctionne presque comme de l héritage classique . Bien sur c est pas encore parfait ;
on est obligé d 'écrire a chaque fois les appels a la classe de base de spécifier chaque fois les appels au prototype  voyons comment automatiser tout ça :

En premier abord on est tenté de créer une fonction qui va faire appels précédents a notre place  par exemple étendre l'objet Function    de Javascript ainsi que Object  cette fonction on va l inclure a chaque fois .
Exemple de fonction pour l héritage :

if(typeof Function.prototype.extends != "function"){
    Function.prototype.extends=function (base){
             this.prototype = new base();
               this.prototype.constructor = this;    
    }
}


if(typeof Object.prototype.extends != "function"){
 Object.prototype.extends=function (base){
     (arguments.length>1)?
      base.apply(this,Array.prototype.slice.call(arguments,1)):
      base.call(this);
 }
}




Salarie.extends(Personne);
    
function Salarie (nom ,profession){
           
       this.extends(Personne,nom )
       this.salaire=1000;
       this.profession=profession;
      
}



var marie=new Salarie ("Marie","Comptable");

alert(marie );//appel toString affiche  [Salarie ]:Marie
alert(marie.profession);   //affiche Comptable


alert(marie.travailler());   //"[Salarie ]: que c'est dur";




Dire qu'on peut déjà s’arrêter là....

a suivre améliorations ....











0 commentaires:

Enregistrer un commentaire