JavaScript Abstract Class
Two main concepts should be considered when working with JavaScript Abstract Classes: Abstraction and Inheritance.
Through abstraction, it enables security, hiding specific details and showing only the essential information of an object, while inheritance takes properties from another class and creates a parent-child relationship between them.
JavaScript Abstract Class
An abstract class is a class that contains one or more abstract methods but cannot instantiate. The abstract classes can’t be instantiated but can extend using methods.
In addition, abstract classes need to be inherited, requiring concrete classes or subclasses to extend the abstract class with the methods declared inside it.
Abstract methods are methods that can only be declared but have no implementation.
First, we can define an abstract class and create a constructor within it. After that, we must define the functions when extending the abstract class.
For this example, we have defined Fruit
as the abstract class name and created two methods inside it: color()
to indicate the fruit’s color and eat()
to find whether the fruit has been consumed or not.
Since all the fruits we have taken here as examples can be consumed, we implemented the method to display them as eating
within the abstract class. But when we define each concrete class, we must implement the method color()
for each of them.
class Fruit {
constructor() {
if (this.constructor == Fruit) {
throw new Error('Abstract classes can\'t be instantiated.');
}
}
color() {
throw new Error('Method \'color()\' must be implemented.');
}
eat() {
console.log('eating');
}
}
Extend the Abstract Class with Concrete Classes
After creating the abstract class, we have to create concrete classes. When building concrete classes, we should make them inherit all the functions and behavior of the abstract class.
The snippet below shows the concrete classes Apple
and Orange
created for the abstract class. Using the extends
keyword, it performs the inheritance.
class Apple extends Fruit {
color() {
console.log('Red');
}
}
class Orange extends Fruit {
color() {
console.log('Orange');
}
}
By defining abstract classes and concrete classes, abstraction and inheritance have been achieved.
The complete code consists when combining the above code snippets and the complete code with the result shown in the figures. Here both concrete classes are called the abstract class, which displays the output implemented in the methods.
Apart from that, when the constructor has the same name as the abstract class, it throws an error. But when instantiating with the concrete classes, it works flawlessly.
Code:
// Abstract Class 'Fruit'.
class Fruit {
constructor() {
if (this.constructor == Fruit) {
throw new Error('Abstract classes can\'t be instantiated.');
}
}
// Method 'color'
color() {
throw new Error('Method \'color()\' must be implemented.');
}
// Method 'eat'
eat() {
console.log('eating');
}
}
// Concrete class 'Apple'
class Apple extends Fruit {
color() {
console.log('Red');
}
}
// Concrete class 'Orange'
class Orange extends Fruit {
color() {
console.log('Orange');
}
}
// Calling the classes
new Apple().eat();
new Orange().eat();
new Apple().color();
new Orange().color();
Output:
Even the concrete class Apple
has implemented the color()
method within it, but banana()
has not. Therefore, the concrete class banana()
inherits only the abstract class properties.
So when the method color()
calls over, the banana
throws an error instead of printing the color.
The below code snippet highly depicts the inheritance concept.
// Abstract class 'Fruit'
class Fruit {
constructor() {
if (this.constructor == Fruit) {
throw new Error('Abstract classes can\'t be instantiated.');
}
}
// Method 'color'
color() {
throw new Error('Method \'color()\' must be implemented.');
}
// Method 'eat'
eat() {
console.log('eating');
}
}
// Concrete class 'Apple'
class Apple extends Fruit {
color() {
console.log('Red');
}
}
// Concrete class 'Banana'
class Banana extends Fruit {}
// Calling the classes
new Apple().eat();
new Banana().eat();
new Apple().color();
new Banana().color();
Output:
Apart, creating an instance also throws an error. As abstract classes can’t be instantiated, we can’t call over them.
Code:
// Abstract class 'Fruit'
class Fruit {
constructor() {
if (this.constructor == Fruit) {
throw new Error('Abstract classes can\'t be instantiated.');
}
}
// Method 'color'
color() {
throw new Error('Method \'color()\' must be implemented.');
}
// Method 'eat'
eat() {
console.log('eating');
}
}
// Concrete class 'Apple'
class Apple extends Fruit {
color() {
console.log('Red');
}
}
// Calling the class
new Fruit();
Output:
Conclusion
Overall, having this abstraction feature in JavaScript and other OOP languages enhances the understandability and maintainability of code for the developer and the reader and reduces code duplication.
Nimesha is a Full-stack Software Engineer for more than five years, he loves technology, as technology has the power to solve our many problems within just a minute. He have been contributing to various projects over the last 5+ years and working with almost all the so-called 03 tiers(DB, M-Tier, and Client). Recently, he has started working with DevOps technologies such as Azure administration, Kubernetes, Terraform automation, and Bash scripting as well.