Polymorphism in OOP Fundamentals – Dynamic Binding, Overriding, Overloading, Generics
This post is a terminology guide to polymorphism in OOP, complete with exam questions and tags.
In a Nutshell
Polymorphism allows a single method call to invoke different concrete implementations based on context, typically resolved at runtime. The result is flexible, extensible software with lower coupling to specific types.
Core Definition
Polymorphism is the ability of objects to respond differently to the same message depending on their actual type. At its heart lies dynamic binding: method calls are resolved at runtime via dispatch tables or vtables to the correct implementation. We distinguish three main forms: subtype polymorphism through interfaces and inheritance, parametric polymorphism through generics, and ad hoc polymorphism through overloading. Polymorphic design supports the Open/Closed Principle—extensions come from new types rather than changes to existing ones.
Key Exam Points
- Subtype polymorphism: usage via base type or interface, concrete implementation bound at runtime
- Parametric polymorphism: generics enable one algorithm to work with many types, type-safe without casting
- Ad hoc polymorphism: overloading uses the same name with different parameters, resolved statically
- IHK-relevant: explain the distinction between overriding and overloading clearly, understand dynamic versus static binding
- Practice: the Strategy pattern exploits polymorphism for behavior swapping without if-else chains
- Security aspect: contracts and invariants prevent faulty substitution; validate inputs
- Economics: reduces maintenance costs through extensibility and fewer conditional branches
- Documentation requirement: describe interface contracts, preconditions, postconditions, and side effects explicitly
Core Components
- Contract interface: method signatures and semantics
- Implementations: concrete classes and strategies
- Dynamic dispatch: vtable, single dispatch
- Static dispatch: compile-time resolution during overloading
- Generics: type parameters and constraints
- Testability: contract and substitution tests
- Design patterns: Strategy, Template Method, Visitor
- Error handling: exceptions compatible with the base interface
- Performance considerations: indirect calls, inlining, JIT optimization
- Tool support: UML, class diagrams, sequence diagrams
Practical Example
// Subtype polymorphism via Strategy
interface PaymentMethod {
Receipt pay(int cents)
}
class CreditCard implements PaymentMethod {
public Receipt pay(int cents) {
// authorization, clearing
return new Receipt("credit card", cents)
}
}
class PayPal implements PaymentMethod {
public Receipt pay(int cents) {
// token, capture
return new Receipt("paypal", cents)
}
}
class CheckoutService {
private PaymentMethod method
public CheckoutService(PaymentMethod method) { this.method = method }
public Receipt checkout(int cents) {
if (cents <= 0) throw new IllegalArgumentException("positive amount required")
return method.pay(cents)
}
}
Explanation: CheckoutService communicates only with the PaymentMethod interface; concrete implementations are swapped interchangeably.
Advantages and Disadvantages
Advantages
- Clear separation between contract and implementation
- Better extensibility, reduced conditional logic
- Higher testability through mocks and stubs
- Promotes reuse and encapsulation
Disadvantages
- Indirect calls complicate debugging and performance analysis
- Vague or incorrect contracts lead to substitution errors
- Overly complex hierarchies increase cognitive load
Typical Exam Questions (with Short Answers)
-
What is polymorphism in OOP? The ability for different objects to be addressed through the same contract while executing type-specific implementations at runtime.
-
Overloading versus overriding? Overloading: same method name, different parameters, static binding. Overriding: inherited method is reimplemented with the same signature, dynamic binding.
-
How does it support the Open/Closed Principle? New variants are added as new implementations of an existing interface; existing code remains unchanged.
-
What does the Liskov Substitution Principle require? Subclasses and implementations must honor the promises of the base type: do not strengthen preconditions, do not weaken postconditions, and preserve invariants.
-
Practical example without if-else cascades? Payment methods as strategies behind a PaymentMethod interface; selection happens through the concrete implementation, not through branching.
-
Forms of polymorphism? Subtype polymorphism, parametric polymorphism via generics, ad hoc polymorphism via overloading, and less commonly multiple dispatch and the Visitor pattern.
-
How to test polymorphism effectively? Define a contract test suite against the interface and run it against all implementations; additionally, use mock-based interaction tests.
-
Duck typing and its limits? Behavior is valid if required methods exist; no explicit type relationship needed. Flexible but offers less compile-time safety.
Key Resources
- https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
- https://de.wikipedia.org/wiki/Polymorphie_(Programmierung)
- https://martinfowler.com/bliki/Polymorphism.html
Continue Your OOP Learning Path
All OOP articles are now complete. Return to the first article: Object-Oriented Programming OOP Fundamentals.



