Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save alex-shamshurin/38610574bd9d8491d955401b032954b4 to your computer and use it in GitHub Desktop.
Save alex-shamshurin/38610574bd9d8491d955401b032954b4 to your computer and use it in GitHub Desktop.
ES6 Abstract Class Example
'use strict';
class Abstract {
// A static abstract method.
static foo() {
if (this === Abstract) {
// Error Type 2. Abstract methods can not be called directly.
throw new TypeError("Can not call static abstract method foo.");
} else if (this.foo === Abstract.foo) {
// Error Type 3. The child has not implemented this method.
throw new TypeError("Please implement static abstract method foo.");
} else {
// Error Type 5. The child has implemented this method but also called `super.foo()`.
throw new TypeError("Do not call static abstract method foo from child.");
}
}
constructor() {
if (this.constructor === Abstract) {
// Error Type 1. Abstract class can not be constructed.
throw new TypeError("Can not construct abstract class.");
}
//else (called from child)
// Check if all instance methods are implemented.
if (this.foo === Abstract.prototype.foo) {
// Error Type 4. Child has not implemented this abstract method.
throw new TypeError("Please implement abstract method foo.");
}
}
// An abstract method.
foo() {
// Error Type 6. The child has implemented this method but also called `super.foo()`.
throw new TypeError("Do not call abstract method foo from child.");
}
}
// Error Type 1.
//let bar = new Abstract(); // Throws because abstract class can not be constructed.
// Error Type 2.
//Abstract.foo(); // Throws because static abstract methods can not be called.
class ChildA extends Abstract {}
// Error Type 3.
//ChildA.foo(); // Throws because ChildA does not implement static abstract method foo.
// Error Type 4.
//let bar = new ChildA(); // Throws because ChildA does not implement abstract method foo.
class ChildB extends Abstract {
static foo() {
// Calls Abstract.foo();
super.foo();
}
foo() {
// Calls Abstract.prototype.foo();
super.foo();
}
}
// Error Type 5.
//ChildB.foo(); // Throws because in ChildB the implementation calls the static abstract method foo.
// Error Type 6.
//(new ChildB()).foo(); // Throws because in ChildB the implementation calls the abstract method foo.
class ChildC extends Abstract {
static foo() {
// Implementation of abstract static method.
console.log('ChildC.foo');
}
constructor() {
super();
// Implementation of constructor.
}
foo() {
// Implementation of abstract method.
console.log('ChildC.prototype.foo');
}
}
// Success.
ChildC.foo();
let bar = new ChildC();
bar.foo();
@acarkaan
Copy link

thanks very explanatory example.

@GabenGar
Copy link

Does it require to write error throwing boilerplate for every single property/method? I guess it's really painful to do without typescript.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment