Polymorphism: One Operation, Different Implementations
Display different records through one operation
A school report includes attendance and marks summaries. The report should ask each summary for descriptive text without hard-coding every summary type.
Polymorphism lets different values respond to a common operation with their own implementations. The caller depends on a compatible behavior contract.
Identify the common operation
Find the shared method the caller uses.
Trace the receiver
Explain why different objects return different text.
Check compatibility
Recognize that a matching name alone is not a matching contract.
One report call, different summary text
Attendance summary
Implements a text-producing describe method.
Present: 28Marks summary
Implements the same operation for marks.
Total: 75Report loop
Calls describe on either receiver.
Common interface
The caller asks for behavior rather than a type label
If each summary promises describe() returning a string, the caller can invoke that operation without checking its class. JavaScript permits this kind of structural use without a shared parent class.
This is often called duck typing: use the behavior a value supports. The metaphor is limited—real compatibility includes accepted arguments, returned meaning, side effects and failure behavior, not only a method name.
Before starting, review shared contracts and overriding. These examples use JavaScript; other languages can use different syntax and rules.
Read both summaries with the same call
Each object defines describe using method syntax. The loop calls the current object’s implementation, so two different strings are produced.
No branch checks “is this attendance?” The supported operation handles that distinction.
JavaScript · local teaching example
const summaries = [
{ describe() { return 'Present: 28'; } },
{ describe() { return 'Total: 75'; } }
];
for (const summary of summaries) {
console.log(summary.describe());
}Expected output
Present: 28
Total: 75Add another compatible summary
A library summary can join the report without changing its loop, provided it returns descriptive text.
This is an extension of the interface contract, not proof that every arbitrary object belongs in the list.
JavaScript · local teaching example
const summaries = [
{ describe() { return 'Books borrowed: 2'; } }
];
for (const summary of summaries) console.log(summary.describe());Expected output
Books borrowed: 2Apply the rule to a small change
Add a trip summary returning “Trip confirmed” and display it through the same describe operation.
Worked answer
The report uses the unchanged method call. The new object supplies its own implementation, so extending the summaries does not require a new classification branch.
JavaScript · local teaching example
const summary = {
describe() { return 'Trip confirmed'; }
};
console.log(summary.describe());Expected output
Trip confirmedRecognize mistakes and limits
An object with describe returning a Promise is not interchangeable with these synchronous string-returning objects unless the caller’s contract allows asynchronous results. Similar names can hide different behavior.
Method overloading and overriding are related terms but not identical to all forms of polymorphism. Language support varies. Avoid forcing unrelated objects into a vague method whose meaning changes from one receiver to another.
For the language or tool rules used here, see JavaScript class behavior.
Check the core idea
JavaScript · code for this question
const summaries = [
{ describe() { return 'Present: 28'; } },
{ describe() { return 'Total: 75'; } }
];
for (const summary of summaries) {
console.log(summary.describe());
}Apply the idea to a new situation
Make the common behavior precise
Polymorphism lets one caller use several implementations through a compatible operation. Inheritance is one route, but JavaScript objects can support a shared contract without it.
Connect this idea with interface contracts and asynchronous result handling.
Reaching the recap and completing the quizzes are separate milestones.