Πολυμορφισμός είναι η δυνατότητα μίας μεθόδου να κάνει διαφορετικές ενέργειες ανάλογα με τον τύπο του αντικειμένου πάνω στο οποίο δρα.
Οι τύποι πολυμορφισμού είναι:
• Η υπερκάλυψη (overriding)
• Η υπερφόρτωση (overloading)
• Η δυναμική συσχέτιση μεθόδων (dynamic method binding)
Έστω ότι έχουμε τον παρακάτω κώδικα

Overriding

class A {
int a;
void add(int x) {
a += x;}
}
Και
class B extends A {
a : float; // Αλλάζει τον τύπο της α.
void add(int x) { // Αλλάζει την add(int x).
// Αυτό λέγεται overriding.
a = a + ((float) x);
print(a);
}
}

Η μεταβολή κάποιου πεδίου ή μεθόδου, που κληρονομήθηκε από την κλάση Α στην κλάση Β, λέγεται υπερκάλυψη (overriding) του πεδίου/μεθόδου της Α από το αντίστοιχο πεδίο/μέθοδο της Β.
ο μεταγλωττιστής «ξέρει» πότε να καλέσει ποια μέθοδο, βασισμένος στον τύπο του τρέχοντος αντικειμένου. Προσέξτε ότι η μέθοδος της Β που κάνει override έχει το ίδιο όνομα, λίστα παραμέτρων και επιστρεφόμενο τύπο με αυτήν της Α. Αν δεν είναι τα ίδια τότε δεν έχουμε υπερκάλυψη αλλά ορισμό μιας νέας μεθόδου.

Overloading

class number {
int a;
void add(int x) {
a += x;
}
void add(float f) {
a += ((int) f);
}
void add(number n) {
a += n.get_a();
}
int get_a() {
return a;
}
}

Βλέπουμε δηλαδή ότι η συνάρτηση void add(...) χρησιμοποιείται πολλές φορές (3) αλλά κάθε φορά με διαφορετική λίστα παραμέτρων. Αυτή η επαναχρησιμοποίηση του ίδιου ονόματος λέγεται υπερφόρτωση (overloading) του ονόματος αυτού.
Στις object oriented γλώσσες επιτρέπεται ο ορισμός μίας μεθόδου με τι ίδιο όνομα δύο ή περισσότερες φορές αρκεί να έχουν διαφορετικές λίστες παραμέτρων. Παράδειγμα :
aMethod(), aMethod(type1), aMethod(type2), aMethod(type1, type2), aMethod(type2, type1).
Όλες οι παραπάνω μέθοδοι είναι διαφορετικές μεταξύ τους. Έτσι, κατά την κλήση μιας μεθόδου κατ' αρχήν εξετάζεται το όνομά της και έπειτα εξετάζεται και η λίστα των παραμέτρων της, όσον αφορά το πλήθος, τον τύπο και τη σειρά των παραμέτρων. Αυτό είναι μια μορφή πολυμορφισμού .

Dynamic method binding

Υποθέστε ότι τρεις υποκλάσεις (Cow, Dog και Snake) έχουν δημιουργηθεί χρησιμοποιώντας την αφηρημένη (abstract) κλάση Animal, με κάθε μια από τις οποίες να υλοποιεί την δική της μέθοδο speak().

public class AnimalReference {
public static void main(String[] args) {
Animal ref; // set up a reference for an Animal
// make specific objects
Cow aCow = new Cow("Bossy");
Dog aDog = new Dog("Rover");
Snake aSnake = new Snake("Earnie");
// now reference each as an Animal
ref = aCow;
ref.speak();
ref = aDog;
ref.speak();
ref = aSnake;
ref.speak();
}


Παρατηρήστε ότι αν και η κλήση της μεθόδου speak() έγινε σε αναφορά τύπου Animal, το πρόγραμμα μπορεί να αποφανθεί για την σωστή μέθοδο (ανάλογα με την υποκλάση) και τον χρόνο εκτέλεσης. Αυτό ονομάζεται δυναμική συσχέτιση μεθόδων (dynamic method binding).