Skip to content

Instantly share code, notes, and snippets.

@Zodiase
Last active July 18, 2022 11:03
Show Gist options
  • Save Zodiase/af44115098b20d69c531 to your computer and use it in GitHub Desktop.
Save Zodiase/af44115098b20d69c531 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();
@lambduli
Copy link

Hey Zodiase, why don't you use new.target insead? Are there some edge cases?

@gormat
Copy link

gormat commented Nov 2, 2016

@taskkill new.target is not supported in safari.
new.target is good method if u will use it in node.js.

@Zodiase
Copy link
Author

Zodiase commented Jan 17, 2017

@taskkill OMG I just realized Gist doesn't support notifications and I didn't see your question until I was scanning through my gists today. Ironically, since there's no notification, you probably wouldn't see this reply either (just guessing). But yeah as @gormat pointed out, new.target is not well supported.
image

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