2012-12-07 11 views
7

Possible Duplicate:
set attribute with javascript super methodWywołanie metody z nadklasy Podklasa - JavaScript

Próbuję stworzyć prostą grę w HTML5 dla zabawy. Mam klasę Entity, która ma być nadklasą klasy Player.

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; 

Problem jest w tym wierszu:

this.parent.tick.call(this); 

otrzymuję komunikat o błędzie wyświetlany w konsoli JavaScript w Chrome: "Uncaught TypeError: nie można wywołać metodę 'zadzwoń' undefined".

Nie rozumiem tego i spędziłem dużo czasu próbując znaleźć posty o podobnym problemie. Moje wezwanie do konstruktora superklasy działa dobrze, ale wywołanie metody klasy "nadklasy" nie działa.

Jestem bardzo nowy w tworzeniu gier, więc nie mam pojęcia, czy to dobra konfiguracja (wywołanie tykl klasy nadrzędnej z tykla podklasy). Jeśli istnieje lepszy, bardziej typowy sposób, w jaki ludzie używają, proszę powiedzieć.

Dzięki.

+0

Dlaczego nie masz ogólnych rzeczy na prototypie? Możesz tam z łatwością uzyskać do niego dostęp. – Bergi

+0

javascript nie ma dziedziczenia klasycznego, podobnie jak w innych językach klasycznych, takich jak java. Powinieneś przeczytać dziedziczenie prototypowe i dowiedzieć się o jego różnicach w stosunku do klasycznego. – Christoph

Odpowiedz

7

Adaptacja this answer do kodu:

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

Mam wątpliwości. Dlaczego musimy przekazać 'this' w:' this.parent.constructor.call (this, x, y); '. Wiem, że to by działało w ten sposób. ale nie znajduję żadnego wytłumaczenia tego. –

+0

@VeerShrivastav: Musisz przekazać instancję, ponieważ w przeciwnym razie konstruktor nie będzie wiedział, gdzie ustawić jego właściwości. – Bergi

4

Twoje pytanie zainspirowało mnie do rozejrzeć i znalazłam to, co myślę jest a great article by Josh Gertzen o tym pojęcia.

I bezczelnie skopiować ze swoim artykule jakiś kod, aby skonfigurować metodę extends na klasy:

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; 
}; 

Po czym sprawa jest tak proste, jak:

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(); 

Który będzie ostrzegać Player tick a następnie Entity tick.

+10

Wygląda na to, że mam do czynienia z nadmierną komplikacją :-) – Bergi

+0

+1 za wysiłek, chociaż odpowiedź Bergiego jest czystsza. – WTK

+2

Jeśli jest to jedyne wywołanie nadklasy w aplikacji, oczywiście jest to nadmierna komplikacja. Ale uważam, że drugi blok kodu jest jaśniejszy niż inne metody. Musisz tylko raz skopiować i wkleić pierwszy blok, a potem o nim zapomnieć; nie trzeba już myśleć o prototypach :-) – Mark

Powiązane problemy