Introduction
Polymorphism is one of the most powerful features of Object-Oriented Programming (OOP). It allows different objects to respond differently to the same method call. In JavaScript, polymorphism is primarily achieved through inheritance and method overriding.
Instead of writing separate code for every object type, developers can write generic code that works with multiple objects. Each object executes its own implementation of the method, making applications flexible, scalable, and easier to maintain.
In real-world Node.js applications, polymorphism is used in payment systems, notification services, employee management systems, file processing, API integrations, and many other scenarios.
For automation engineers, polymorphism is widely used in Playwright, Selenium, and Cypress frameworks where different page objects, browser classes, API clients, and reporting modules implement common methods differently.
In this tutorial, you’ll explore practical examples of polymorphism in Node.js.
Example 1: Animal Sounds
Different animals produce different sounds.
class Animal {
sound() {
console.log(
"Animal makes a sound."
);
}
}
class Dog extends Animal {
sound() {
console.log(
"Dog barks."
);
}
}
class Cat extends Animal {
sound() {
console.log(
"Cat meows."
);
}
}
const animals = [
new Dog(),
new Cat()
];
animals.forEach(animal => {
animal.sound();
});
Sample Output
Dog barks.
Cat meows.
Example 2: Employee Management System
Different employee roles perform different work.
class Employee {
work() {
console.log(
"Employee is working."
);
}
}
class Developer extends Employee {
work() {
console.log(
"Writing code."
);
}
}
class Tester extends Employee {
work() {
console.log(
"Testing application."
);
}
}
const employees = [
new Developer(),
new Tester()
];
employees.forEach(employee => {
employee.work();
});
Sample Output
Writing code.
Testing application.
Example 3: Payment System
Different payment methods process payments differently.
class Payment {
pay() {
console.log(
"Processing payment."
);
}
}
class CreditCard extends Payment {
pay() {
console.log(
"Payment using Credit Card."
);
}
}
class UPI extends Payment {
pay() {
console.log(
"Payment using UPI."
);
}
}
class Cash extends Payment {
pay() {
console.log(
"Payment using Cash."
);
}
}
const payments = [
new CreditCard(),
new UPI(),
new Cash()
];
payments.forEach(payment => {
payment.pay();
});
Sample Output
Payment using Credit Card.
Payment using UPI.
Payment using Cash.
Example 4: Notification System
Different notification services.
class Notification {
send() {
console.log(
"Sending notification."
);
}
}
class EmailNotification extends Notification {
send() {
console.log(
"Sending Email."
);
}
}
class SmsNotification extends Notification {
send() {
console.log(
"Sending SMS."
);
}
}
class PushNotification extends Notification {
send() {
console.log(
"Sending Push Notification."
);
}
}
const notifications = [
new EmailNotification(),
new SmsNotification(),
new PushNotification()
];
notifications.forEach(notification => {
notification.send();
});
Sample Output
Sending Email.
Sending SMS.
Sending Push Notification.
Example 5: File Processing System
Different file types are processed differently.
class FileProcessor {
process() {
console.log(
"Processing file."
);
}
}
class CsvProcessor extends FileProcessor {
process() {
console.log(
"Processing CSV file."
);
}
}
class JsonProcessor extends FileProcessor {
process() {
console.log(
"Processing JSON file."
);
}
}
const files = [
new CsvProcessor(),
new JsonProcessor()
];
files.forEach(file => {
file.process();
});
Sample Output
Processing CSV file.
Processing JSON file.
Example 6: Playwright Automation Example
Different page objects implement login differently.
class BasePage {
login() {
console.log(
"Default login."
);
}
}
class AdminPage extends BasePage {
login() {
console.log(
"Admin login."
);
}
}
class CustomerPage extends BasePage {
login() {
console.log(
"Customer login."
);
}
}
const pages = [
new AdminPage(),
new CustomerPage()
];
pages.forEach(page => {
page.login();
});
Sample Output
Admin login.
Customer login.
Example 7: Selenium Automation Example
Different browsers.
class Browser {
launch() {
console.log(
"Launching browser."
);
}
}
class ChromeBrowser extends Browser {
launch() {
console.log(
"Launching Chrome."
);
}
}
class FirefoxBrowser extends Browser {
launch() {
console.log(
"Launching Firefox."
);
}
}
const browsers = [
new ChromeBrowser(),
new FirefoxBrowser()
];
browsers.forEach(browser => {
browser.launch();
});
Sample Output
Launching Chrome.
Launching Firefox.
Example 8: Cypress Automation Example
Different application pages.
class BaseCommands {
openPage() {
console.log(
"Opening page."
);
}
}
class DashboardPage extends BaseCommands {
openPage() {
console.log(
"Opening Dashboard."
);
}
}
class SettingsPage extends BaseCommands {
openPage() {
console.log(
"Opening Settings."
);
}
}
const pages = [
new DashboardPage(),
new SettingsPage()
];
pages.forEach(page => {
page.openPage();
});
Sample Output
Opening Dashboard.
Opening Settings.
Example 9: API Testing Example
Different API services.
class ApiService {
sendRequest() {
console.log(
"Sending API request."
);
}
}
class UserApi extends ApiService {
sendRequest() {
console.log(
"Sending User API request."
);
}
}
class ProductApi extends ApiService {
sendRequest() {
console.log(
"Sending Product API request."
);
}
}
const apis = [
new UserApi(),
new ProductApi()
];
apis.forEach(api => {
api.sendRequest();
});
Sample Output
Sending User API request.
Sending Product API request.
Example 10: Report Generation System
Different report types.
class Report {
generate() {
console.log(
"Generating report."
);
}
}
class PdfReport extends Report {
generate() {
console.log(
"Generating PDF report."
);
}
}
class ExcelReport extends Report {
generate() {
console.log(
"Generating Excel report."
);
}
}
const reports = [
new PdfReport(),
new ExcelReport()
];
reports.forEach(report => {
report.generate();
});
Sample Output
Generating PDF report.
Generating Excel report.
Common Mistakes
Forgetting to Override the Method
If the child class does not override the parent method, the parent implementation is executed.
Using Different Method Names
Method overriding requires the child class to use the same method name as the parent class.
Forgetting the extends Keyword
Without inheritance, polymorphism cannot be achieved using method overriding.
Best Practices
-
Create generic parent classes.
-
Override methods only when behavior should change.
-
Keep method names consistent across parent and child classes.
-
Use
super.methodName()when parent behavior should also be executed. -
Avoid duplicate code.
-
Keep child classes focused on specialized behavior.
-
Design reusable class hierarchies.
Conclusion
Polymorphism enables different objects to respond differently to the same method call, making applications flexible, scalable, and easier to maintain. In JavaScript, it is commonly implemented using inheritance and method overriding.
For automation engineers, polymorphism is widely used to create reusable Page Object Models (POM), browser classes, API clients, reporting modules, and other framework components where each object provides its own implementation of common methods.
Mastering polymorphism will help you write cleaner, more reusable, and more maintainable Node.js applications.
Frequently Asked Questions (FAQs)
What is polymorphism?
Polymorphism is the ability of different objects to respond differently to the same method call.
How is polymorphism achieved in JavaScript?
It is primarily achieved through inheritance and method overriding.
Why is polymorphism useful?
It improves code reuse, flexibility, maintainability, and scalability.
Can multiple child classes override the same method?
Yes. Each child class can provide its own implementation of the inherited method.
Why is polymorphism important in automation testing?
It allows different page objects, browser classes, API clients, and reusable framework components to implement common methods differently while maintaining a consistent interface.
Key Takeaways
-
Polymorphism means “many forms.”
-
Different objects can execute different implementations of the same method.
-
JavaScript achieves polymorphism through inheritance and method overriding.
-
Polymorphism improves flexibility and code reuse.
-
Parent classes define common behavior, while child classes provide specialized implementations.
-
The same method call can produce different results depending on the object.
-
Polymorphism is widely used in Playwright, Selenium, Cypress, and API testing frameworks.
-
Use
superwhen parent behavior should also be executed. -
Keep parent classes generic and child classes specialized.
-
Polymorphism is a fundamental principle of Object-Oriented Programming in Node.js.
