• 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
7 years ago

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

this.constructor === Widget

0
Juan
Juan
6 years ago

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

1
Hritik Vijay
Hritik Vijay
4 years ago

A nicely crafted write up. Thanks !

0
Dominic Rose
Dominic Rose
3 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

  • I Joined Truth Social Using a VPN and Editing Some HTML to Bypass the Phone Verification
  • Testing Event Listeners In Jest (Without Using A Library)
  • How To Get The Hash of A File In Node.js
  • Thoughts on the Flipper Zero
  • Waiting for an Element to Exist With JavaScript
  • How To Paginate An Array In Javascript
  • How To Mock uuid In Jest
  • How To Decompile And Compile Android APK's On A Mac Using Apktool
  • How To Get Last 4 Digits of A Credit Card Number in Javascript
  • Wild Natural Deodorant Review

Recent Comments

  • CJ on Microsoft Modern Wireless Headset Review
  • Dwayne on Microsoft Modern Wireless Headset Review
  • CJ on Microsoft Modern Wireless Headset Review
  • john on Microsoft Modern Wireless Headset Review
  • Dwayne on Why You Should Be Using globalThis Instead of Window In Your Javascript Code

Copyright © 2023 · Dwayne Charrington · Log in

wpDiscuz