2012-12-07 6 views
7

Possible Duplicate:
set attribute with javascript super methodAufruf Oberklassenmethode Von Subclass - JavaScript

Ich versuche, ein einfaches Spiel in HTML5 für Spaß zu schaffen. Ich habe eine Entity-Klasse, die die Superklasse der Player-Klasse sein soll.

function Entity(x, y) { 

    this.x = x; 
    this.y = y; 

    this.tick = function() { 
     //Do generic stuff 
    } 
} 

function Player(x, y) { 

    this.parent.constructor.call(this, x, y); 

    this.tick = function() { 
     //Do player-specific stuff 
     this.parent.tick.call(this); 
    } 
} 

Player.prototype = new Entity(); 
Player.prototype.constructor = Player; 
Player.prototype.parent = Entity.prototype; 

Das Problem ist in dieser Zeile:

this.parent.tick.call(this); 

ich einen Fehler in der JavaScript-Konsole aus Chrom angezeigt zu bekommen: „Nicht abgefangene Typeerror: Die Methode kann nicht nennen‚nennen‘undefinierter“.

Ich bekomme es nicht und ich habe lange Zeit versucht, Posts mit einem ähnlichen Problem zu finden. Mein Aufruf zum Konstruktor der Superklasse funktioniert einwandfrei, aber die Methode zum Aufruf der Superklasse funktioniert nicht.

Ich bin sehr neu in der Herstellung von Spielen, also habe ich keine Ahnung, ob dies ein gutes Setup (Aufruf Superklasse Tick aus Unterklasse Tick). Wenn es eine bessere, typischere Art gibt, die Leute benutzen, erzählen Sie bitte.

Danke.

+0

Warum haben Sie nicht das generische Zeug auf dem Prototyp? Sie könnten dort leicht zugreifen. – Bergi

+0

JavaScript hat keine klassische Vererbung, wie Sie von anderen klassischen Sprachen wie Java gewohnt sind. Sie sollten in die prototypische Vererbung einlesen und etwas über ihre Unterschiede zur klassischen lernen. – Christoph

Antwort

7

Anpassung this answer an Ihrem Code:

function Entity(x, y) { 

    this.x = x; 
    this.y = y; 

    this.tick = function() { 
     //Do generic stuff 
    } 
} 

function Player(x, y) { 

    this.parent.constructor.call(this, x, y); 

    var oldtick = this.tick; 
    this.tick = function() { 
     //Do player-specific stuff 
     oldtick.call(this); 
    } 
} 

Player.prototype = Object.create(Entity.prototype); 
Player.prototype.constructor = Player; 
Player.prototype.parent = Entity.prototype; 
+0

Ich habe Zweifel. Warum müssen wir 'this' in:' this.parent.constructor.call (this, x, y); '. Nun, ich weiß, das würde so funktionieren. aber ich finde keine Erklärung dafür. –

+0

@VeerShrivastav: Sie müssen die Instanz übergeben, da andernfalls der Konstruktor nicht weiß, wo er seine Eigenschaften einrichten soll. – Bergi

4

Ihre Frage mich inspiriert umschauen und ich fand, was ich denke a great article by Josh Gertzen über dieses Konzept.

Ich kopiere eklatant von seinem Artikel einige Code ein extends Methode auf Klassen einzurichten:

function Class() { } 
Class.prototype.construct = function() {}; 
Class.extend = function(def) 
{ 
    var classDef = function() 
    { 
     if (arguments[0] !== Class) 
     { 
      this.construct.apply(this, arguments); 
     } 
    }; 
    var proto = new this(Class); 
    var superClass = this.prototype; 
    for (var n in def) 
    { 
     var item = def[n];      
     if (item instanceof Function) item.$ = superClass; 
     proto[n] = item; 
    } 
    classDef.prototype = proto; 
    classDef.extend = this.extend;  
    return classDef; 
}; 

Nach dem Ihr Fall ist so einfach wie:

var Entity = Class.extend({ 
    tick: function() 
    { 
     alert('Entity tick'); 
    } 
}); 

var Player = Entity.extend({ 
    tick: function() 
    { 
     alert('Player tick'); 
     arguments.callee.$.tick.call(this); 
    } 
}); 

p = new Player(); 
p.tick(); 

Welche Player tick aufmerksam wird und dann Entity tick.

+10

Sieht aus wie eine Überkompilierung für mich :-) – Bergi

+0

+1 für die Mühe, obwohl Bergi Antwort sauberer ist. – WTK

+2

Wenn dies der einzige Superklassenaufruf in der Anwendung ist, ist es natürlich eine Überkompilierung. Aber ich finde, dass der zweite Block des Codes klarer ist als die anderen Methoden. Und Sie müssen den ersten Block nur einmal kopieren und einfügen und dann vergessen; Ich denke nicht mehr über Prototypen nach :-) – Mark