Πολυμορφισμός σε μια κλάση αναφέρεται στην ικανότητά της να παρουσιάζει διαφορετική συμπεριφορά με βάση τον τύπο του αντικειμένου που την καλεί. Αυτό σημαίνει ότι οι μέθοδοι μιας κλάσης μπορούν να υλοποιηθούν με διαφορετικό τρόπο ανάλογα με την κλάση ή τον υποτύπο του αντικειμένου που τις καλεί.
Πολυμορφισμός κατά την κληρονομικότητα σημαίνει ότι μια υποκλάση μπορεί να υλοποιήσει μια μέθοδο της γονικής κλάσης με διαφορετικό τρόπο. Έτσι, η ίδια μέθοδος μπορεί να έχει διαφορετική συμπεριφορά σε κάθε κλάση που την κληρονομεί.
Ο πολυμορφισμός είναι ένα σημαντικό χαρακτηριστικό της αντικειμενοστραφούς προγραμματισμού, καθώς επιτρέπει την επαναχρησιμοποίηση και την ευελιξία του κώδικα.
Παρακάτω παρουσιάζεται ένα παράδειγμα:
class Bird: def fly(self): print("Τα πουλιά μπορούν να πετάξουν.") class Airplane: def fly(self): print("Τα αεροπλάνα μπορούν επίσης να πετάξουν.") # Δημιουργία αντικειμένων bird = Bird() # Δημιουργία αντικειμένου της κλάσης Bird και αποθήκευση στη μεταβλητή bird airplane = Airplane() # Δημιουργία αντικειμένου της κλάσης Airplane και αποθήκευση στη μεταβλητή airplane # Κλήση της μεθόδου fly() για κάθε αντικείμενο bird.fly() # Κλήση της μεθόδου fly() για το αντικείμενο bird που ανήκει στην κλάση Bird airplane.fly() # Κλήση της μεθόδου fly() για το αντικείμενο airplane που ανήκει στην κλάση Airplane
Ο παραπάνω κώδικας δημιουργεί δύο κλάσεις, Bird
και Airplane
, που έχουν μια μέθοδο με το όνομα fly()
. Η μέθοδος fly()
στην κλάση Bird
εκτυπώνει το μήνυμα “Τα πουλιά μπορούν να πετάξουν.”, ενώ η μέθοδος fly()
στην κλάση Airplane
εκτυπώνει το μήνυμα “Τα αεροπλάνα μπορούν επίσης να πετάξουν.”
Στη συνέχεια, δημιουργούνται δύο αντικείμενα: ένα αντικείμενο με την κλάση Bird
που αποθηκεύεται στη μεταβλητή bird
, και ένα αντικείμενο με την κλάση Airplane
που αποθηκεύεται στη μεταβλητή airplane
.
Τέλος, καλείται η μέθοδος fly()
για το αντικείμενο bird
, με αποτέλεσμα να εκτυπωθεί το μήνυμα “Τα πουλιά μπορούν να πετάξουν.”, και καλείται η μέθοδος fly()
για το αντικείμενο airplane
, με αποτέλεσμα να εκτυπωθεί το μήνυμα “Τα αεροπλάνα μπορούν επίσης να πετάξουν.”
[adinserter block=”2″]
Ένα άλλο παράδειγμα πολυμορφίας είναι η χρήση της κληρονομικότητας και της υπερκάλυψης μεθόδων:
class Animal: def speak(self): pass # Κενή μέθοδος, δεν πραγματοποιείται καμία ενέργεια class Dog(Animal): def speak(self): print("Το σκύλος λέει: Γαβ!") # Εκτύπωση μηνύματος "Το σκύλος λέει: Γαβ!" class Cat(Animal): def speak(self): print("Η γάτα λέει: Νιάου!") # Εκτύπωση μηνύματος "Η γάτα λέει: Νιάου!" # Δημιουργία αντικειμένων dog = Dog() # Δημιουργία αντικειμένου της κλάσης Dog cat = Cat() # Δημιουργία αντικειμένου της κλάσης Cat # Κλήση της μεθόδου speak() για κάθε αντικείμενο dog.speak() # Κλήση της μεθόδου speak() για το αντικείμενο dog cat.speak() # Κλήση της μεθόδου speak() για το αντικείμενο cat
Ο παραπάνω κώδικας ορίζει τρεις κλάσεις: Animal
, Dog
και Cat
. Η κλάση Animal
είναι μια βασική κλάση που έχει μια μέθοδο speak()
που δεν πραγματοποιεί κάποια ενέργεια. Οι κλάσεις Dog
και Cat
κληρονομούν από την κλάση Animal
και κάθε μία από αυτές υλοποιεί τη μέθοδο speak()
με διαφορετικό τρόπο.
Στη συνέχεια, δημιουργούνται δύο αντικείμενα: ένα αντικείμενο της κλάσης Dog
με τη μεταβλητή dog
και ένα αντικείμενο της κλάσης Cat
με τη μεταβλητή cat
.
Τέλος, καλούνται οι μέθοδοι speak()
για τα αντικείμενα dog
και cat
, με αποτέλεσμα να εκτυπώνονται τα αντίστοιχα μηνύματα:
Το σκύλος λέει: Γαβ! Η γάτα λέει: Νιάου!
Έτσι, ο κώδικας εκτελεί τις αντίστοιχες ενέργειες για τα αντικείμενα των κλάσεων Dog
και Cat
και εμφανίζει τα κατάλληλα μηνύματα.
Μπορούμε να χρησιμοποιήσουμε πολυμορφία με κλάσεις και υποκλάσεις που έχουν το ίδιο όνομα μεθόδου. Μια υποκλάση μπορεί να υπερκαλύψει μια μέθοδο από την γονική κλάση, επιτρέποντας στην υποκλάση να έχει τη δική της εκδοχή της μεθόδου. Αυτό είναι ένα παράδειγμα πολυμορφίας μέσω κληρονομικότητας και υπερκάλυψης μεθόδων.
Παρακάτω παρουσιάζεται ένα παράδειγμα:
class Vehicle: def move(self): print("Το όχημα κινείται.") class Car(Vehicle): def move(self): print("Το αυτοκίνητο κινείται.") class Boat(Vehicle): def move(self): print("Το σκάφος κινείται.") # Δημιουργία αντικειμένων vehicle = Vehicle() # Δημιουργία ενός αντικειμένου της κλάσης Vehicle car = Car() # Δημιουργία ενός αντικειμένου της κλάσης Car boat = Boat() # Δημιουργία ενός αντικειμένου της κλάσης Boat # Κλήση της μεθόδου move() για κάθε αντικείμενο vehicle.move() # Κλήση της μεθόδου move() για το αντικείμενο vehicle της κλάσης Vehicle car.move() # Κλήση της μεθόδου move() για το αντικείμενο car της κλάσης Car boat.move() # Κλήση της μεθόδου move() για το αντικείμενο boat της κλάσης Boat
[adinserter block=”3″]
Ο παραπάνω κώδικας ορίζει τρεις κλάσεις: Vehicle
, Car
και Boat
, που αντιπροσωπεύουν οχήματα. Η κλάση Vehicle
είναι η γονική κλάση και έχει μια μέθοδο move()
που εκτυπώνει το μήνυμα “Το όχημα κινείται.”.
Οι κλάσεις Car
και Boat
κληρονομούν από την κλάση Vehicle
και καθένα από αυτές έχει μια μέθοδο move()
που εκτυπώνει το κατάλληλο μήνυμα για το αυτοκίνητο και το σκάφος αντίστοιχα.
Στη συνέχεια, δημιουργούνται τρία αντικείμενα: vehicle
, car
και boat
, τα οποία ανήκουν στις κλάσεις Vehicle
, Car
και Boat
αντίστοιχα.
Τέλος, καλείται η μέθοδος move()
για κάθε αντικείμενο. Έτσι, το μήνυμα “Το όχημα κινείται.” εκτυπώνεται για το αντικείμενο vehicle
, το μήνυμα “Το αυτοκίνητο κινείται.” εκτυπώνεται για το αντικείμενο car
, και το μήνυμα “Το σκάφος κινείται.” εκτυπώνεται για το αντικείμενο boat
.
Η πολυμορφία μας επιτρέπει να προσαρμόζουμε τη συμπεριφορά των κλάσεων και των υποκλάσεων ανάλογα με το πώς θέλουμε να λειτουργήσουν, επιτρέποντας στον κώδικα να είναι πιο ευέλικτος και επαναχρησιμοποιήσιμος. Επίσης, αυτό μας επιτρέπει να γράφουμε κώδικα που μπορεί να δουλέψει με διάφορα αντικείμενα τύπου, ανεξάρτητα από την εσωτερική υλοποίησή τους, αρκεί να παρέχουν την ίδια διεπαφή (όπως οι μέθοδοι με το ίδιο όνομα).
Αυτή η ευελιξία και η ανεξαρτησία του κώδικα από τις εσωτερικές λεπτομέρειες των κλάσεων και των υποκλάσεων είναι μια από τις βασικές αρχές του αντικειμενοστραφούς προγραμματισμού και κάνει τον κώδικα πιο εύκολο στη συντήρηση και την επέκταση.