• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

I Like Kill Nerds

The blog of Australian Front End / Aurelia Javascript Developer & brewing aficionado Dwayne Charrington // Aurelia.io Core Team member.

  • Home
  • Aurelia 2
  • Aurelia 1
  • About
  • Aurelia 2 Consulting/Freelance Work

Abstract Classes In Javascript

ES2015 (aka ES6), Javascript · June 26, 2015

Modern Javascript is a lot different to Javascript of 2010. We have considerably more methods and means of doing things that we did not have previously. Some of those include classes, generators, arrow functions and a few other high-profile additions.

One aspect of Javascript that not even ES2015 nor ES2016 covers is the concept of abstract classes. The ability to specify a class that defines how child classes should look, more specifically ensuring they specify certain methods.

Recently whilst working on an Aurelia project, I was building a widget based system where a base widget class defines a few core values and methods, then the child class which is a certain type of widget extends and defines the contents of the widget.

One such requirement was the base widget class cannot be instantiated. Another requirement is all child widgets must implement a schema method which returns the schema for a particular widget.

Preventing base class from being instantiated

Due to how classes are implemented in ES6, we can check the constructor knowing that any class that extends the Widget class is going to have a different constructor because it’s a new class and therefore a new instance. We just check in the base widget class if the constructor is “Widget” or not. If it is, we can assume someone is trying to instantiate the widget class directly via: let myInstance = new Widget() which our code will stop.

class Widget {
    constructor() {
        if (this.constructor === Widget) {
            throw new TypeError('Abstract class "Widget" cannot be instantiated directly.'); 
        }
    }
}

Enforcing implented methods

To require an inherited child class implements our required method, we can check for its existence via this which allows us to see if the required method has been defined. We will take the above example and add in another check for our child class method.

class Widget {
    constructor() {
        if (this.constructor === Widget) {
            throw new TypeError('Abstract class "Widget" cannot be instantiated directly.'); 
        }

        if (this.schema === undefined) {
            throw new TypeError('Classes extending the widget abstract class');
        }
    }
}

class PieChart extends Widget {
    constructor() {
        super();
    }

    get schema() {
        return {
            "name": "PIE_CHART",
            "data": []
        }
    }
}

Conclusion

We might eventually get a native solution, but for the moment we can easily implement our own fake abstract class implementation in Javascript using classes and it will work for most purposes. I haven’t encountered any issues with the above solutions.

Dwayne

Leave a Reply Cancel reply

5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Torgeir Helgevold
Torgeir Helgevold
7 years ago

I think as the JavaScript community starts to embrace classes and related concepts – we will start to see more parity between ES6 classes and classes from languages like C#, Java etc.

Right now I am just happy to see classes as a concept make it into ES6, but I would definitely like to see more advanced structures like abstract, scope modifiers, overriding etc make it in as well. Not sure the UI community will push for it, but server side JS will likely miss it at some point.

1
Borg
Borg
6 years ago

Nice article. Correct me if I’m wrong but the constructor check is legal ES5 right?

this.constructor === Widget

0
Juan
Juan
5 years ago

May be using new.target.name over this.constructor.

1
Hritik Vijay
Hritik Vijay
3 years ago

A nicely crafted write up. Thanks !

0
Dominic Rose
Dominic Rose
2 years ago

you may want to raise an error only on method call

class AbstractClass {
subclassResponsibility() {
throw new Error(‘subclass responsibility’)
}
}

class Widget extends AbstractClass {
aMethodToOverride() {
this.subclassResponsibility()
}
}

1

Primary Sidebar

Popular

  • Testing Event Listeners In Jest (Without Using A Library)
  • How To Get The Hash of A File In Node.js
  • Web 3.0 may have died before it even started
  • Smoke Detector Randomly Goes Off Early Hours of The Morning
  • NBN Box Installed Inside of Garage, Where Do You Put The Modem?
  • How to Copy Files Using the Copy Webpack Plugin (without copying the entire folder structure)
  • How To Install Eufy Security Cameras Without Drilling or Using Screws
  • How To Calculate A Javascript Date X Months Ago With Vanilla Javascript
  • How to Use Neural DSP Archetype Plugins With the Quad Cortex
  • Which Neural DSP Archetype Plugins Should You Buy?

Recent Comments

  • Casey Milne on A List of WordPress Gutenberg Core Blocks
  • Jay on Neural DSP Reveal Details About the Long-Awaited Quad Cortex Desktop Editor
  • john on Deno Raises $21M – but is anyone using it yet?
  • Oranges on How To Store Users In Firestore Using Firebase Authentication
  • Precious on Fixing Sequel Pro SQL Encoding Error For Imported SQL Files

Copyright © 2022 · Dwayne Charrington · Log in

wpDiscuz