Disons que vous avez le code ci-dessous:
function A() {
function modify() {
x = 300;
y = 400;
}
var c = new C();
}
function B() {
function modify(){
x = 3000;
y = 4000;
}
var c = new C();
}
C = function () {
var x = 10;
var y = 20;
function modify() {
x = 30;
y = 40;
};
modify();
alert("The sum is: " + (x+y));
}
Maintenant , la question est, s'il y a une façon dont je peux passer outre la méthode modify
de C
les méthodes qui sont A
et B
. En Java, vous utiliseriez le super
mot clé, mais comment pouvez-vous réaliser quelque chose comme ça en JavaScript?
javascript
oop
overriding
Daniel Nastase
la source
la source
modify
n'est pas une méthode mais une fonction imbriquée - il y a une différence entre ces deux ...super
mot - clé pour accéder aux champs et méthodes non privés d'une super-classe. Vous ne l'utilisez pas pour les remplacer.Réponses:
Edit: Cela fait maintenant six ans que la réponse originale a été écrite et beaucoup de choses ont changé!
Bonne chance!
L'héritage JavaScript est un peu différent de Java. Voici à quoi ressemble le système d'objets JavaScript natif:
// Create a class function Vehicle(color){ this.color = color; } // Add an instance method Vehicle.prototype.go = function(){ return "Underway in " + this.color; } // Add a second class function Car(color){ this.color = color; } // And declare it is a subclass of the first Car.prototype = new Vehicle(); // Override the instance method Car.prototype.go = function(){ return Vehicle.prototype.go.call(this) + " car" } // Create some instances and see the overridden behavior. var v = new Vehicle("blue"); v.go() // "Underway in blue" var c = new Car("red"); c.go() // "Underway in red car"
Malheureusement, c'est un peu moche et cela n'inclut pas une très belle façon de "super": vous devez spécifier manuellement la méthode des classes parentes que vous voulez appeler. En conséquence, il existe une variété d'outils pour rendre la création de classes plus agréable. Essayez de regarder Prototype.js, Backbone.js ou une bibliothèque similaire qui inclut une syntaxe plus agréable pour faire la POO dans js.
la source
Puisqu'il s'agit d'un succès sur Google, j'aimerais donner une réponse mise à jour.
L' utilisation des classes ES6 facilite beaucoup l'héritage et le remplacement de méthode:
'use strict'; class A { speak() { console.log("I'm A"); } } class B extends A { speak() { super.speak(); console.log("I'm B"); } } var a = new A(); a.speak(); // Output: // I'm A var b = new B(); b.speak(); // Output: // I'm A // I'm B
Le
super
mot-clé fait référence à la classe parente lorsqu'il est utilisé dans la classe héritière. De plus, toutes les méthodes de la classe parent sont liées à l'instance de l'enfant, vous n'avez donc pas besoin d'écriresuper.method.apply(this);
.En ce qui concerne la compatibilité: le tableau de compatibilité ES6 ne montre que les versions les plus récentes des classes de support des principaux joueurs (principalement). Les navigateurs V8 les ont depuis janvier de cette année (Chrome et Opera), et Firefox, utilisant le moteur SpiderMonkey JS, verra des cours le mois prochain avec leur version officielle Firefox 45. Côté mobile, Android ne prend toujours pas en charge cette fonctionnalité, tandis qu'iOS 9, sorti il y a cinq mois, est partiellement pris en charge.
Heureusement, il existe Babel , une bibliothèque JS pour recompiler le code Harmony en code ES5. Les classes et de nombreuses autres fonctionnalités intéressantes d'ES6 peuvent rendre votre code Javascript beaucoup plus lisible et maintenable.
la source
Une fois devrait éviter d'émuler OO classique et utiliser OO prototypique à la place. Les traits sont une belle bibliothèque utilitaire pour OO prototypique .
Plutôt que d'écraser les méthodes et de configurer des chaînes d'héritage (il faut toujours privilégier la composition d'objets par rapport à l'héritage d'objets), vous devez regrouper les fonctions réutilisables en traits et créer des objets avec ceux-ci.
Exemple en direct
var modifyA = { modify: function() { this.x = 300; this.y = 400; } }; var modifyB = { modify: function() { this.x = 3000; this.y = 4000; } }; C = function(trait) { var o = Object.create(Object.prototype, Trait(trait)); o.modify(); console.log("sum : " + (o.x + o.y)); return o; } //C(modifyA); C(modifyB);
la source
modify () dans votre exemple est une fonction privée, qui ne sera accessible de nulle part que dans votre définition A, B ou C. Vous devrez le déclarer comme
this.modify = function(){}
C n'a pas de référence à ses parents, à moins que vous ne le passiez à C. Si C est configuré pour hériter de A ou B, il héritera de ses méthodes publiques (pas de ses fonctions privées comme vous avez défini modify ()). Une fois que C hérite des méthodes de son parent, vous pouvez remplacer les méthodes héritées.
la source
la méthode
modify()
que vous avez appelée dans le dernier est appelée dans un contexte global si vous souhaitez remplacermodify()
vous devez d'abord hériterA
ouB
.Peut-être que vous essayez de faire ceci:
Dans ce cas
C
hériteA
function A() { this.modify = function() { alert("in A"); } } function B() { this.modify = function() { alert("in B"); } } C = function() { this.modify = function() { alert("in C"); }; C.prototype.modify(); // you can call this method where you need to call modify of the parent class } C.prototype = new A();
la source
C.prototype.modify()
aurait la mauvaisethis
valeur. À savoirC.prototype
au lieu de l'instance de c. Veuillez utiliser,.call(this)
mais votre réponse n'est qu'un double :)Sauf si vous rendez toutes les variables "publiques", c'est-à-dire en les rendant membres de
Function
laprototype
propriété soit directement, soit via la propriété.var C = function( ) { this.x = 10 , this.y = 20 ; this.modify = function( ) { this.x = 30 , this.y = 40 ; console.log("(!) C >> " + (this.x + this.y) ) ; } ; } ; var A = function( ) { this.modify = function( ) { this.x = 300 , this.y = 400 ; console.log("(!) A >> " + (this.x + this.y) ) ; } ; } ; A.prototype = new C ; var B = function( ) { this.modify = function( ) { this.x = 3000 , this.y = 4000 ; console.log("(!) B >> " + (this.x + this.y) ) ; } ; } ; new C( ).modify( ) ; new A( ).modify( ) ; new B( ).modify( ) ;
Vous remarquerez quelques changements.
Plus important encore, l'appel au constructeur supposé "super-classes" est désormais implicite dans cette ligne:
<name>.prototype = new C ;
Les deux
A
etB
auront désormais des membres individuellement modifiablesx
ety
ce qui ne serait pas le cas si nous avions écrit à la... = C
place.Ensuite,
x
,y
et quemodify
tous les membres « publics » afin que l' attribution d' un autreFunction
pour les<name>.prototype.modify = function( ) { /* ... */ }
"remplacera" l'original
Function
par ce nom.Enfin, l'appel à
modify
ne peut pas être fait dans laFunction
déclaration car l'appel implicite à la "super-classe" serait alors à nouveau exécuté lorsque nous positionnerions la "super-classe"prototype
supposée à la propriété des "sous-classes" supposées.Mais bon, c'est plus ou moins comment vous feriez ce genre de chose en JavaScript.
HTH,
FK
la source
<name>.prototype = new C;
observer tous les membres du prototype de toute façonObjects
partageraient le même membreC
si vous n'instanciez pas unC
objet. Ainsi, l' évolutionx
enA
changeraitx
dansC
et ainsi changerx
enB
. Ce qui est évidemment indésirable.A
etB
hériter deC
. Si cette ligne manquait, ce ne serait pas le cas. En fait, le seul prototype à la foisA
ainsi queB
le "shadow" aurait accès dans ce cas seraitObject.prototype
.x
,y
et d'modify
ombre et donc tousC
les membres « . Quel est l'intérêt de mettre C dans le prototype si vous ne l'utilisez pas? C'est du code mort.function A() { var c = new C(); c.modify = function(){ c.x = 123; c.y = 333; } c.sum(); } function B() { var c = new C(); c.modify = function(){ c.x = 999; c.y = 333; } c.sum(); } C = function () { this.x = 10; this.y = 20; this.modify = function() { this.x = 30; this.y = 40; }; this.sum = function(){ this.modify(); console.log("The sum is: " + (this.x+this.y)); } } A(); B();
la source