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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

[OO] Implémentation de l'héritage ET d'appels super()


Sujet :

JavaScript

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 253
    Par défaut [OO] Implémentation de l'héritage ET d'appels super()
    Bonjour à tous,

    J'utilise actuellement le script de John Resig pour fournir de l'héritage à mes "classes" Javascript mais sa méthode de déclaration par objet littéral ne permet pas de fourni des fonctionnalités intéressantes en termes de scope (i.e. les variable sont uniquement publiques et on ne peut pas faire de différence entre publique/privée, etc... sans déclarer ça à côté, après la déclaration de l'objet -> dégeulasse).

    Je cherche donc une manière de déclarer mes classes sous forme de fonction où il est possible de différencier les scopes comme évoqué dans cet article : Robert Nymann.

    Mais voila, je perds un aspect important de la programmation objet à mon sens : l'appel à super() que Resig inclue nativement dans son script.
    Je ne vois pas comment le reproduire lorsque les classes sont déclarées comme Robert Nymann le préconise.

    Est-ce que quelqu'un aurait une idée, l'a déjà réalisé? Ca me permettrai à la fois d'avoir les scopes, plus l'héritage et super (qui ne nécessite pas de répendre le nom de la classe parent à tous les 4 coins du fichier sinon en effet il est facile de reproduire cet appel avec le prototype du parent).
    En vous remerciant par avance, je sais que JS n'est pas un langage à vocation à faire de l'objet mais vu qu'on peut y arriver je saisi l'opportunité comme je le peux.

  2. #2
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Billets dans le blog
    20
    Par défaut
    je sais que JS n'est pas un langage à vocation à faire de l'objet
    Heu... si au contraire
    Sauf que ce n'est pas de l'OO par classes mais par prototype.
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  3. #3
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    J'avais fais un truc du genre y'a un an (mon niveau JS était pas terrible en fait à l’époque) donc si je devais le refaire aujourd'hui, je le ferai différemment et bien mieux.

  4. #4
    Invité
    Invité(e)
    Par défaut
    salut,

    je nuance le commentaire de Bovino.
    Javascript n'est pas spécifiquement orienté objet par prototype.

    Il est possible de faire l'objet. Mais il faut juste aborder l'OO de manière différente de la classique.

    Bien sûr, il est possible de se rapprocher du fonctionnement classique par l'approche prototypale, mais bon, (à ma connaissance), il reste les problèmes de propriétés privées & cie.

    De la même manière une approche uniquement par closure, limite l'approche par super (problème de scope en héritant de fonctions etc), et quand bien même atteinte nécessite de passer par une librarie etc.

    Je pense donc, que vouloir l'approche classique habituelle est mauvaise. Personnellement, je suis plutot fan de l'approche par closure, avec le passage en parametre d'un objet publique partagé parmi la hiérarchie. La raison qui me motive ezt que globalement, il n'y a pas tant que ça de niveau de hiérarchie, (deux ou trois tout au plus), et qu'il faut plutot favoriser beaucoup de composants (par composition justement) plutot qu'une structure verticale.

    Dans ce cas là, certes il faut être cohérent en jonglant in-hiérarchie, mais ca permet de s'en sortir plutot pas mal. Après, c'est vrai qu'il faut réfléchir à ce qu'on fait, et que je manque d'expérience sur des projets d'envergure relative.

  5. #5
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Billets dans le blog
    20
    Par défaut
    Javascript n'est pas spécifiquement orienté objet par prototype.
    Euh... si, c'est même comme ça qu'il est défini.
    En JavaScript, non seulement tout est objet, mais aussi tout possède un prototype. Ensuite, en fonction de ce que l'on fait, il est possible, à l'instar de Mr Jourdain, de faire de l'OO sans le savoir (puisque souvent, on utilise majoritairement des prototypes natifs de JavaScript : String, Number, Function, etc.) mais c'est surtout l'approche procédurale qui n'existe pas à proprement parler en JavaScript.

    Et du coup, je trouve que vouloir reproduire en JavaScript le comportement d'un langage OO par classes est aller à l'encontre de la nature du langage et me semble assez maladroit en général. D'autant que de mémoire, je ne me souviens pas d'un cas où cela m'aurait réellement été utile.

    Ensuite, oui, il est possible de "simuler" des propriétés et méthodes privées et publiques (voire protégées).

    Quant à l'héritage, il se fait simplement par le prototype :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var MaPseudoClasse = function(){};
    MaPseudoClasse.prototype = String.prototype;
    var toto = new MaPseudoClasse();
    alert(toto.toUpperCase);
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  6. #6
    Invité
    Invité(e)
    Par défaut
    Euh... si, c'est même comme ça qu'il est défini.
    En JavaScript, non seulement tout est objet, mais aussi tout possède un prototype
    ui forcément si toute fonction a pour prototype un object (qqsoit le degré de profondeur) l'instanciation va créer un objet.

    En REVANCHE, créer une simple constructeur de la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function propper(){
     return {
      propr1:'oui';
     };
    };
    permet de créer un objet avec lequel il ne sera pas possible d'avoir un prototype "personnalisable" sur l'objet retourné dans la mesure ou le constructeur est déclaré à la volée.

    D'autant que de mémoire, je ne me souviens pas d'un cas où cela m'aurait réellement été utile.
    Voilà un exemple très simple sur lequel j'ai été confronté (peut-être que j'ai pas vu assez loin, c'est possible).

    Tu veux créer le jeu de la vie.
    On crée donc une fonction/constructeur automate.
    Il existe des automates synchrones et asynchrones (asynchrones pour la fourmie de langton par exemple).

    On aurait donc envie de dev une interface du style, tick; refresh, qui actualise l'automate et le met à jour, ainsi que dans les classes filles de défininir tick, et refresh.

    Bon, clairement dans ce cas là, on peut avoir besoin de se servir des services du constructeur parent (dont l'approche classique serait de dire classe abstraite).

    Une approche prototypale force les propriétés du parent et des filles à être publiques...
    une approche par closure permet de conserver les propriétés privées et de réutiliser les méthodes parent par l'objet publique passé en paramètre...

    La question de l'héritage me semble triviale par prototype.
    Dans le cas d'une approche par closure, on ne peut se contenter que d'un couple décorateur/paramètre publique, qui n'est pourtant pas si moche.

    Donc non, l'approche objet en javascript n'est pas forcément prototypale.

  7. #7
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Billets dans le blog
    20
    Par défaut
    @galerien69 : ta fonction propper n'est pas un constructeur
    Un constructeur doit servir à créer des instances de ce constructeur. Ici, il me semble que tu confonds un objet en tant qu'instance de l'objet natif Object et un objet en tant qu'instance d'un constructeur.
    Du coup, pour personnaliser le prototype, c'est celui d'Object qu'il faut utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function propper(){
     return {
      propr1:'oui'
     };
    };
    Object.prototype.deny = function(){
        this.propr1 = 'non'
    };
    var sayYes = new propper();
    alert(sayYes.propr1);
    sayYes.deny();
    alert(sayYes.propr1);


    @fanfouer : désolé si on empiète sur ta question, mais la discussion est intéressante
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  8. #8
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Citation Envoyé par Bovino Voir le message
    Euh... si, c'est même comme ça qu'il est défini.
    En JavaScript, non seulement tout est objet, mais aussi tout possède un prototype. Ensuite, en fonction de ce que l'on fait, il est possible, à l'instar de Mr Jourdain, de faire de l'OO sans le savoir (puisque souvent, on utilise majoritairement des prototypes natifs de JavaScript : String, Number, Function, etc.) mais c'est surtout l'approche procédurale qui n'existe pas à proprement parler en JavaScript.

    Et du coup, je trouve que vouloir reproduire en JavaScript le comportement d'un langage OO par classes est aller à l'encontre de la nature du langage et me semble assez maladroit en général. D'autant que de mémoire, je ne me souviens pas d'un cas où cela m'aurait réellement été utile.

    Ensuite, oui, il est possible de "simuler" des propriétés et méthodes privées et publiques (voire protégées).

    Quant à l'héritage, il se fait simplement par le prototype :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var MaPseudoClasse = function(){};
    MaPseudoClasse.prototype = String.prototype;
    var toto = new MaPseudoClasse();
    alert(toto.toUpperCase);
    Certaines méthodes sont déclaré en même temps que l'objet du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function ConstructeurObjet(){
        this.méthode = function(){alert("je suis inutile");};
    }
    Dans ce cas pour faire un 2 ème constructeur qui héritera de la méthode des objets du premier il faudra aussi faire des "call/apply" du ConstructeurObjet (parent).

    J'ai donc vite recodé tout ça qui à l'air de rudement bien répondre aux bases minimales :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Function.prototype.inherits = function(parent){ 
    	var FN = this;
    	var newFN = function(){
    		parent.apply(this,arguments);
    		this.super = this.super?{super:this.super}:{};
    		for(var i in this)
    			if(typeof this[i] == "function")
    				this.super[i] = this[i];
    		return FN.apply(this,arguments);
    	};	
    	var proto = function(){};
    	proto.prototype = parent.prototype;
    	newFN.prototype = new proto();
    	for(var i in FN.prototype)
    		newFN.prototype[i] = FN.prototype[i];
    	newFN.super = parent;
    	return newFN;
    };

    version avec qqes tests :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    <html><head><script type=text/javascript>
     
     
    Function.prototype.inherits = function(parent){ 
    	var FN = this;
    	var newFN = function(){
    		parent.apply(this,arguments);
    		this.super = this.super?{super:this.super}:{};
    		for(var i in this)
    			if(typeof this[i] == "function")
    				this.super[i] = this[i];
    		return FN.apply(this,arguments);
    	};	
    	var proto = function(){};
    	proto.prototype = parent.prototype;
    	newFN.prototype = new proto();
    	for(var i in FN.prototype)
    		newFN.prototype[i] = FN.prototype[i];
    	newFN.super = parent;
    	return newFN;
    };
     
     
     
    //--------------------------------
     
    /*
    function A(){
    	var privat = "secret";
    	this.getPrivate = function(){return privat;};
    	return this;
    }
     
    function B(){
    	var privat = "nouveau secret";
    	this.public = "info public";
    	this.getPrivate = function(){return privat;};
    	return this;
    }
    B = B.inherits(A);
     
    // console.log
    var l = function(msg){console.log(msg);};
     
    var b = new B();
    l(b.super.getPrivate()); // secret
    l(b.getPrivate()); // nouveau secret
    l(b.public); // info public
    l(b instanceof A); // true
    l(b instanceof B); // true
    l("---------------------------------------------------");
    */
     
    //--------------------------------
     
     
    var wr = function(val){document.write(val,"<hr>");}; 
     
    function A(){
    	this.a=1;
    	this.aa=function(){wr("aa");};
    	this.obj={val:97};
    	this.hard=function(c){
    		wr("a.hard: "+c);
    	};
    	return this;
    }  
    A.prototype.fun = 11; 
    function B(name){
    	this.b=2;
    	this.bb=function(){wr("bb");};
    	this.name=name;
    	this.hard=function(v){
    		wr("b.hard: "+v);
    		this.super.hard(name);
    	};
    	return this;
    }  
    function O(){
    	this.o=3;
    	this.oo=function(){wr("oo");};
    	return this;
    }  
    function H(){
    	this.h=4;
    	this.aa=function(){wr("hh");};
    	this.oo=function(){wr("hh");};
    	return this;
    }  
    H.prototype.fun = 22; 
    var B = B.inherits(A); 
    var H = H.inherits(B);  
    var H = H.inherits(O);  
     
    var h = new H("john smith");  
     
     
     
    wr("=============== FOR EACH IN ( h ) ==============="); 
    for(var i in h)    wr(i+": "+h[i]);  
    // a: 1  
    // b: 2  
    // o: 3  
    // h: 4  
    // func aa : wr hh  
    // func bb : wr bb  
    // func oo : wr hh  
    // parentFN :  ############### object 
    // obj :    object 
    // name : "john smith"  
    // uber :  ############# function 
     
    // overwrited functions  
    wr("=============== OVERWRITED FUNCTIONS ==============="); 
    h.aa(); // hh   
    h.oo(); // hh  
    wr("=============== SUPER/ORIGINAL FUNCTIONS ==============="); 
    // super functions who been overwrited  
    h.super.aa(); // aa  
    h.super.oo(); // oo  
    wr("=============== HERITED FUNCTIONS ==============="); 
    // herited function  
    h.bb(); // bb  
    wr("=============== OBJECTS FROM 2 DIFFERENT INSTANCES ==============="); 
    // test if object1.obj != object2.obj 
    var h2 = new H();  
    h2.obj.val++;  
    wr(h2.obj.val); // 98  
    wr(h.obj.val); // 97  
    wr("=============== PARENTS PROTOTYPE AREN'T MODIFIED ON CHANGE OF CHILD PROTOTYPE ==============="); 
    var a = new A(); 
    wr(a.fun); 
    wr(h.fun); 
    wr("=============== FINAL TEST ==============="); 
    h.hard("Happy End");
     
    </script></head><body></body></html>

    edit: remplacez "super" par un autre mot (uber ou _super) dans le code car je pense que "super" est un mot clé.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Implémentation Runnable et héritage
    Par abdelilah dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 04/03/2010, 01h11
  2. Réponses: 8
    Dernier message: 10/11/2009, 21h41
  3. Héritage et d'appel de méthode
    Par Sunsawe dans le forum Langage
    Réponses: 11
    Dernier message: 30/07/2009, 23h08
  4. Réponses: 7
    Dernier message: 24/09/2008, 11h18
  5. Héritage : problème d'appel de méthodes
    Par parano dans le forum C++
    Réponses: 15
    Dernier message: 02/03/2007, 14h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo