Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 12 of 12
  1. #1
    New Coder
    Join Date
    Sep 2013
    Posts
    20
    Thanks
    4
    Thanked 0 Times in 0 Posts

    Prototypical Inheritance problem

    Hi,
    I have:
    Code:
    function Game(){
    	this.gameManager = new gameManager();
    }
    Game.prototype.getGameManager = function(){
        return this.gameManager;
    }
    And:
    Code:
    function NetworkGame(){
    }
    NetworkGame.prototype = new Game();
    Now I want to do:
    Code:
    var ng = new NetworkGame()
    var gameManager = ng.getGameManager();
    var ng2 = new NetworkGame()
    var gameManager2 = ng2.getGameManager();
    However, now gameManager1 and gameManager2 are the same GameManager-object, but I want ng1 and ng2 to have their own private copy.

    So what I want is that everytime I do: new NetworkGame(), a new Game-object is created and the NetworkGame inherits all methods from it. This is different from the current situation where everytime I do new NetworkGame() I get a NetworkGame object that shares the same Game object as any previously created NetworkGame's.

    Is this even possible? Hope you can help out.

    Grtz Stefan1
    Last edited by stefan1; 10-13-2013 at 12:10 AM. Reason: fixed the type :P

  • #2
    Regular Coder
    Join Date
    Jan 2013
    Location
    Germany
    Posts
    578
    Thanks
    4
    Thanked 77 Times in 77 Posts
    Well of course it will be the same if you call ng.getGameManager twice. But seriously, I know of course that it was just a typo.

    One way to solve this would be "lazy-loading" the GameManager instance, i.e. use this

    Code:
    function Game() {}
    
    Game.prototype.getGameManager = function () {
        if(!this.gameManager) {
            this.gameManager = new GameManager();
        }
    
        return this.gameManager;
    };
    However, if you are going to work heavily object-oriented – which I am all in favor of –, then you might consider using one of the countless OOP libraries for Javascript out there as they will give you anything from lightweight to very powerful tools with entire toolchains to develop in this manner.

    Actually what most libraries will do is not simply assigning an instance of the parent to the child's prototype, but manually copy all properties onto the child. This solves your problem, and it does so "internally", i.e. without you having to care about workarounds like lazy-loading. This also comes closer to, for example, the way inheritance works in Java. The most advanced and Java-like library I know is qooxdoo (more specifically, the qooxdoo core). But like I said, there are also many lightweight class libraries, often with only a couple of dozens of lines of code.
    Last edited by Airblader; 10-12-2013 at 11:45 PM.

  • Users who have thanked Airblader for this post:

    stefan1 (10-13-2013)

  • #3
    New Coder
    Join Date
    Sep 2013
    Posts
    20
    Thanks
    4
    Thanked 0 Times in 0 Posts
    Thanks alot, great answer!

    I haven't tried it yet but it seems like it should work. I guess I will go for the lazy-loading for now, but I was actually just thinking: "I wish inheritance was as easy as in class-based languages", so for future projects I will definitely look into your suggestions.

    Thanks again!


    EDIT: tested, works perfectly
    Last edited by stefan1; 10-13-2013 at 12:23 AM.

  • #4
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,277
    Thanks
    10
    Thanked 581 Times in 562 Posts
    you can also dupe a constructor's properties to add own properties by applying the constructor to the instance:

    replace
    Code:
    function NetworkGame(){
    }
    with
    Code:
    function NetworkGame(){
       Game.apply(this, arguments);
    }
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #5
    New Coder
    Join Date
    Sep 2013
    Posts
    20
    Thanks
    4
    Thanked 0 Times in 0 Posts
    Thanks for the reply.
    I don't fully understand how that works. Doesn't that just call the Game constructor with NetworkGame as context and a set of arguments? What does it really do?

  • #6
    Regular Coder
    Join Date
    Jan 2013
    Location
    Germany
    Posts
    578
    Thanks
    4
    Thanked 77 Times in 77 Posts
    @ rnd_me

    But if you drop setting the prototype in favor of this, i.e. you do this:

    Code:
    function Game () {}
    
    Game.prototype.play = function () {
        alert('Game#play');
    };
    
    function NetworkGame () {
        Game.apply(this, arguments);
    }
    
    var networkGame = new NetworkGame();
    networkGame.play(); // error
    … then this will result in an error because NetworkGame doesn't actually inherit from Game anymore, it only executes the constructor. However, what you could do is this:

    Code:
    function Game () {}
    
    Game.prototype.play = function () {
        alert('Game#play');
    };
    
    function NetworkGame () {
        Game.apply(this, arguments);
    }
    
    NetworkGame.prototype = Game.prototype;
    
    var networkGame = new NetworkGame();
    networkGame.play(); // "Game#play"
    Now you only have to watch out to add prototype methods after having set the prototype, i.e.

    Code:
    function Game () {}
    
    Game.prototype.play = function () {
        alert('Game#play');
    };
    
    function NetworkGame () {
        Game.apply(this, arguments);
    }
    
    NetworkGame.prototype = Game.prototype;
    
    // make sure this is after the above line
    NetworkGame.prototype.play = function () {
        alert('NetworkGame#play');
    };
    
    var networkGame = new NetworkGame();
    networkGame.play(); // "NetworkGame#play"

  • #7
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,277
    Thanks
    10
    Thanked 581 Times in 562 Posts
    Quote Originally Posted by Airblader View Post
    @ rnd_me

    But if you drop setting the prototype in favor of this, i.e. you do this:
    ouch, i didn't say drop the prototype. we want to inherit both the Constructor's "own properties" using apply() and the prototype methods by duping, assigning, or otherwise binding the first prototype to the second Constructor.

    nothing in the OPs code has to fundamentally change, it's a single call change that's compatible with everything else going in the OP's code.

    if you don't assign the proto to a new object or use Object.create(), you'll end up modifying both prototypes at once.
    in your third example, you in-explicitly create a Game.prototype.play(). that might be a good thing in some cases, but i don't think that's what the OP was going for...

    in particular, the combo of apply()ing the constructors to each-other works well after using NetworkGame.prototype = new Game(); to inherit both the protos and owns of Game() on NetworkGame()... An issue with doing only the proto=new Instance routine that is that you turn own properties into inherited ones. that means that if Game() defined this.eventPool=[], each NetworkGame instance would use the exact same event pool array, which could cause problems. By apply()ing the Game to NetworkGame, you create a uniqe eventPool property on every instance, shadowing out the NetworkGame.prototype.eventPool that was created using NetworkGame.prototype=new Game() step.


    in short, the one-two punch of assigning the new constructor's prototype to a new instance of the old and applying the old constructor to the instance of the new is the closest thing to Java-style inheritance of owns and deriveds without resorting to looping or fancy tricks.
    Last edited by rnd me; 10-13-2013 at 09:47 PM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #8
    Regular Coder
    Join Date
    Jan 2013
    Location
    Germany
    Posts
    578
    Thanks
    4
    Thanked 77 Times in 77 Posts
    Sorry, then it was just a misunderstanding. My fault.

  • #9
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,277
    Thanks
    10
    Thanked 581 Times in 562 Posts
    Quote Originally Posted by stefan1 View Post
    Thanks for the reply.
    I don't fully understand how that works. Doesn't that just call the Game constructor with NetworkGame as context and a set of arguments? What does it really do?
    you handle the prototypes just fine, the apply() copies the own properties to the new instance as own properties, instead of putting everything on the prototype, where instances can cross-pollute.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #10
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,277
    Thanks
    10
    Thanked 581 Times in 562 Posts
    Quote Originally Posted by Airblader View Post
    Sorry, then it was just a misunderstanding
    OOP is JS is very easy to misunderstand since we have to recycle so many procedural terms and properties to accomplish Objectivy things. i could have been clearer that i was suggesting to add-on to the code rather than replace it. i think the OP is covered now and knows more than he wanted...
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #11
    New Coder
    Join Date
    Apr 2013
    Posts
    21
    Thanks
    0
    Thanked 1 Time in 1 Post
    Quote Originally Posted by rnd me View Post
    OOP is JS is very easy to misunderstand since we have to recycle so many procedural terms and properties to accomplish Objectivy things. i could have been clearer that i was suggesting to add-on to the code rather than replace it. i think the OP is covered now and knows more than he wanted...
    I believe it was an honest misunderstanding but of course,it's good to clear things out. And,I think he does know what he wanted.

  • #12
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,215
    Thanks
    12
    Thanked 338 Times in 334 Posts
    Quote Originally Posted by Airblader View Post
    This also comes closer to, for example, the way inheritance works in Java. The most advanced and Java-like library I know is qooxdoo (more specifically, the qooxdoo core).
    IMHO, trying to do JavaScript inheritance in a classical (Java) way does more harm than good. it is a fact that JS uses prototypal inheritance and there is no way to getting it 100% behaving like Java. better focus on the strengths of prototypal inheritance and figure out how the Patterns of Class-based OOP should be reformulated*.




    * - one good example for that is the Singleton pattern. in the most simple case that’s a one-liner in JS:
    Code:
    window.singleton = {
        someProperty: "some value"
    };
    (it is not said for nothing that a Singleton is pretty much a global variable)
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •