Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at InVision Office 2012 (New York City) with: Bill Nourse
Ben Nadel at InVision Office 2012 (New York City) with: Bill Nourse@webtimeclock )

Using Static Class Methods To Generate Concrete Instances Of Abstract Classes In JavaScript And Node.js

By Ben Nadel on

The other day, I was building a JavaScript class that depended on another Abstract class as an injected value. The Abstract class only exposed one abstract method that needed to be overridden in a sub-class. I know that not everyone - especially in the Node.js community - is so hot on writing Classes; so, I wanted to see if I could provide a workflow that could consume just the concrete method without having to define an entire sub-class. To do this, I created a static factory function on the abstract class that merged the concrete method into the abstract instance.

JavaScript is enchantingly dynamic (and that's before you even get to ES6 Proxy objects). You can create objects from Prototypes; you can manually construct objects by weaving properties together; or, you can do a little of this and a little of that. And, it's this last approach that I am using in my static factory function. Rather than defining a sub-class, I'm just instantiating the abstract class (because "Abstract" isn't a formal part of the JavaScript language); and then, I'm manually injecting the concrete methods into the abstract instance, thereby "completing" it:

  • class AbstractThing {
  •  
  • // ---
  • // ABSTRACT METHODS.
  • // ---
  •  
  • doThis() {
  • throw( new Error( "Abstract method." ) );
  • }
  •  
  • doThat() {
  • throw( new Error( "Abstract method." ) );
  • }
  •  
  • // ---
  • // PUBLIC METHODS.
  • // ---
  •  
  • execute() {
  • this.doThis();
  • this.doThat();
  • }
  •  
  • // ---
  • // STATIC METHODS.
  • // ---
  •  
  • // I provide a way to create a concrete implementation of the AbstractThing class
  • // by providing the concrete functions. This is in lieu of creating a base class that
  • // extends the AbstractThing class explicitly.
  • static usingFunctions({ doThis, doThat }) {
  •  
  • var implementation = new AbstractThing();
  •  
  • // Override the abstract methods with the given concrete functions.
  • implementation.doThis = doThis;
  • implementation.doThat = doThat;
  •  
  • return( implementation );
  •  
  • }
  •  
  • }
  •  
  • // ----------------------------------------------------------------------------------- //
  • // ----------------------------------------------------------------------------------- //
  •  
  • // Create a concrete instance using the two concrete methods (no base class needed).
  • var thing = AbstractThing.usingFunctions({
  • doThis: function() {
  • console.log( "... do this." );
  • },
  • doThat: function() {
  • console.log( "... do that." );
  • }
  • });
  •  
  • console.log( "Is instance of AbstractThing:", ( thing instanceof AbstractThing ) );
  • thing.execute();

As you can see, the AbstractThing class requires two methods to be overridden in its sub-classes: doThis() and doThat(). The static method, usingFunctions(), takes these two required methods, instantiates the AbstractThing class and then, manually overrides the abstract methods with the given concrete ones.

When we run this code though Node.js, we get the following terminal output:


 
 
 

 
 Using static methods to generate concrete instances of abstract classes in JavaScript. 
 
 
 

Works like a charm. There's no magic here, really. This is just JavaScript being JavaScript, which is why JavaScript is so awesome. Of course, this approach only works if there's no additional constructor logic needed by the concrete class. But, if you only need to provide one or two functions (which can be powered by lexical scoping rather than constructor arguments), this seems like a fun little pattern to use.



Looking For A New Job?

Ooops, there are no jobs. Post one now for only $29 and own this real estate!

100% of job board revenue is donated to Kiva. Loans that change livesFind out more »

Reader Comments

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.