17

I like the module pattern that returns constructors as described in: http://elegantcode.com/2011/02/15/basic-javascript-part-10-the-module-pattern/

However I am not sure how to inherit from an object that is implemented with this pattern. Suppose I have a parent object implemented thus...

namespace('MINE');  

MINE.parent = (function() { 
    // private funcs and vars here

    // Public API - constructor
    var Parent = function (coords) {
       // ...do constructor stuff here
    };

    // Public API - prototype
    Parent.prototype = {
       constructor: Parent,
       func1:  function ()    { ... },
       func2:  function ()    { ... }
    }

    return Parent;
 }());

How do I define a child object that also uses the module pattern that inherits from parent in such a way that I can selectively override, for example, func2?

Langdon
  • 19,875
  • 18
  • 88
  • 107
  • Just a note, the code you've provided has a bug -- you're setting the constructor to `undefined`. I've edited to fix it. – Langdon Jun 18 '12 at 17:51
  • I just asked a similar question here http://stackoverflow.com/questions/16659326/simple-javascript-inheritance-using-extend-and-module-pattern - wondering what you think of it. – Ron Gilchrist May 21 '13 at 18:33

2 Answers2

18
MINE.child = (function () {

  var Child = function (coords) {
    Parent.call(this, arguments);    
  }

  Child.prototype = Object.create(Parent.prototype);

  Child.prototype.constructor = Child;
  Child.prototype.func2 = function () { ... };

  return Child;

}());
Raynos
  • 166,823
  • 56
  • 351
  • 396
  • 1
    Thank you. This was a very terse and clear answer and worked fine for me. I do like this pattern because it encompasses one-time initialization, encapsulation and with your code above, inheritance. Do you see any major pitfalls to the pattern? –  Dec 31 '11 at 04:10
  • @AndrewS. I personally hate namespaces. But that's a style preference. You can use module loaders instead. – Raynos Dec 31 '11 at 11:09
  • This isn't working for me. If I were to instantiate a MINE.child, I can't access func1 (as defined in MINE.parent). Am I missing something?? And is the child's func2 supposed to replace the parent's func2? – Jay Querido Apr 05 '12 at 19:36
  • 1
    The problem with this approach is that you can have an equivalent of static variable, but not private variable. I'm still looking for a better way. – juminoz Feb 13 '13 at 23:35
  • 2
    @juminoz the only non-horrendously-hacky way I know of doing private instance variables is to define them in the constructor and define all methods that rely on them in the constructor too, with this.method = . Unfortunately I strongly dislike this way of doing things, as it creates a new function object for every instance rather than reusing the one on the prototype. I tend to avoid using private instance variables for that reason. – kybernetikos Dec 09 '13 at 01:25
  • private variables are easy. just use a weakmap keyed to `this` – Raynos Dec 09 '13 at 16:33
  • @Raynos if you're writing es6 already then I envy you! Having said that, if I were using es6, I'd probably use Symbols to do private variables. – kybernetikos Dec 11 '13 at 10:40
1

I find the solution from this blog (http://metaduck.com/08-module-pattern-inheritance.html) cleaner. For example:

function Parent(name) {
    // Private variables here
    var myName;

    // Constructor
    myName = name;

    // Public interface
    return {
        func1: function () {alert("Parent func1. Name: " + myName); },
        func2: function () {alert("Parent func2. Name: " + myName); }
    }
}

function Child(name) {
    // Private variables here
    var myName,
        exportObj;

    // Constructor
    // Inherit
    exportObj = Parent(name + "'s father");

    // Override
    exportObj.func2 = function () {
        alert("Child func2. Name: " + name);
    }

    // Export public interface
    return exportObj;
}

An example can be run here: http://jsfiddle.net/wt4wcuLc/

Javier Uria
  • 119
  • 6