ΕΙΣΑΓΩΓΗ
Στο σημερινό δωρεάν μάθημα Java θα εξηγήσουμε τι ακριβώς είναι η διαδικασία overriding μιας μεθόδου και πως η λέξη κλειδί super συνδυάζεται με αυτή.
Για να μπορέσουμε να αναλύσουμε καλύτερα την θεωρία μας, θα συνεχίσουμε με το παράδειγμα του εργαζόμενου και θα χτίσουμε επάνω στις κλάσεις που ήδη έχετε γράψει.
INHERITANCE EXAMPLE
Επειδή υπάρχει κληρονομικότητα ανάμεσα στις κλάσεις του παραδείγματος μας, μπορούμε να δημιουργήσουμε ένα αντικείμενο Salary είτε ένα αντικείμενο Manager. Για να δούμε τον μισθό του αντικειμένου Salary θα πρέπει να καλέσουμε την payment( ) μέθοδο, ενώ για να δούμε τον μισθό του Manager θα πρέπει να καλέσουμε την μέθοδο bonus( ) αντίστοιχα. Ας δούμε λοιπόν τι έχουμε μέχρι τώρα.
Employee.java
Salary.java
Manager.java
EmployeeDemo.java
Output
Hello Michail
Your payment plus your bonus is: 1384.6153846153848
Αν και το πρόγραμμα μας δουλεύει για το σκοπό που δημιουργήθηκε (έχουμε παραλείψει έξτρα κώδικα όπως getter και setter μεθόδους), κάπως μπερδεύει τον προγραμματιστή όταν μέσα στην EmployeeDemo κλάση πρέπει να καλέσει ένα όνομα μεθόδου για να δει τον μισθό του Salary και διαφορετικό όνομα μεθόδου για να δει τον μισθό του Manager. Σε μια αρκετά μεγάλη εφαρμογή με εκατοντάδες κλάσεις αυτό θα είναι λίγο δύσκολο να το ακολουθήσει κάποιος. Το επιθυμητό θα ήταν να υπάρχει μια κοινή μέθοδο για όλες τις κλάσεις, όπως για παράδειγμα payment( ). Μέσα σε κάθε κλάση η payment( ) θα περιέχει τον αντίστοιχο κώδικα που αντιπροσωπεύει την σωστή πληροφορία είτε είναι για τον Salary είτε για τον Manager. Το τελικό αποτέλεσμα θα είναι να υπάρχει μια μέθοδος με το ίδιο όνομα (αλλά διαφορετικό κώδικα) σε όλες τις κλάσεις. Με αυτό τον τρόπο από όποια κλάση και αν κάνουμε αντικείμενο θα γνωρίζουμε ότι καλώντας την payment( ) μέθοδο θα πάρουμε τον μισθό του αντίστοιχου αντικειμένου.
METHOD OVERRIDING
Στην Java, ο πρακτικός τρόπος να δώσουμε αυτή την δομή στο πρόγραμμα μας είναι να ξαναγράψουμε τον κώδικα για μεθόδους που κληρονομούμε. Αυτή την διαδικασία την ονομάζουμε method overriding γιατί πολύ απλά γράφεις ξανά τον κώδικα της μεθόδου που κληρονομείς κρατώντας ίδιο το signature. Αυτή την δυνατότητα την έχουμε λόγω της κληρονομικότητας.
Όταν όμως κάνουμε override μια μέθοδο, η java θέλει να ακολουθήσουμε τρεις απλούς κανόνες:
- Το signature της μεθόδου, δηλαδή το return type, method name και parameter list πρέπει να παραμείνουν τα ίδια
- Ο access specifier πρέπει να είναι τουλάχιστον ίδιος, ή πιο χαλαρός με εκείνον της κλάσης από την οποία κληρονόμησες την μέθοδο. Δηλαδή αν έχουμε κληρονομήσει μια μέθοδο που έχει access specifier protected, τότε στην δική μας κλάση μπορούμε να δώσουμε είτε τον ίδιο access specifier στην μέθοδο ή πιο χαλαρό όπως public, όχι όμως private. Με την ίδια λογική εάν κληρονομήσουμε μια μέθοδο με public access specifier τότε θα πρέπει και εμείς να κρατήσουμε το public.
- Τέλος, δεν επιτρέπεται από την java, η δική μας μέθοδο να επιστρέφει περισσότερα exceptions από την αρχική. Για τα exceptions θα μιλήσουμε σε μελλοντική ενότητα.
Προσέξτε με τους δύο όρους override και overload. Το overload όπως έχουμε ήδη εξηγήσει σε προηγούμενη ενότητα, σημαίνει ότι αλλάζω τον αριθμό και είδος των παραμέτρων (parameter list) σε μια μέθοδο ενώ κρατάω ίδιο μόνο το όνομα της. Το override σημαίνει ότι αφήνω τον ορισμό της μεθόδου αυτούσιο και απλά αλλάζω τον κώδικα που περιέχει ή προσθέτω επιπλέον κώδικα σε αυτόν που ήδη περιέχει.
Στο δικό μας παράδειγμα λοιπόν, θα μπορούσαμε αντί να γράψουμε μια καινούργια μέθοδο bonus( ) μέσα στην κλάση Manager, να κάναμε override την μέθοδο payment που κληρονομούμε από την Salary και να αλλάξουμε τον κώδικα της έτσι ώστε να δείχνει τον σωστό κώδικα για την κλάση Manager. Το τελικό αποτέλεσμα είναι ότι όταν πάμε στην κλάση EmployeeDemo να δημιουργήσουμε αντικείμενο είτε από κλάση Salary είτε από την κλάση Manager, η μέθοδος payment( ) θα σας δώσει το σωστό αποτέλεσμα για το αντίστοιχο αντικείμενο. Ας δούμε λοιπόν πως αλλάζει ο κώδικας μας. Αυτή η αλλαγή θα γίνει κυρίως στην Manager (μέσα στην οποία θα κάνουμε το override).
Manager.java
EmployeeDemo.java
Output
Hello Michail
Your payment plus your bonus is: 1384.6153846153848
CALLING SUPER
Αν και στην κλάση Manager κάναμε override την μέθοδο payment γράφοντας τον δικό μας κώδικα, για ακόμη μια φορά δεν είμαστε ικανοποιημένοι γιατί πολύ απλά γράψαμε όλο τον κώδικα της payment από την αρχή και στο τέλος προσθέσαμε το bonus. Το ιδανικό σενάριο θα ήταν να καλούσαμε την μέθοδο payment όπως έχει γραφτεί στην Salary και απλά να προσθέσουμε τον έξτρα κώδικα. Αυτό ακριβώς μας επιτρέπει να κάνουμε η λέξη super. Με την super μπορούμε να καλέσουμε μεταβλητές ή μεθόδους από την κλάση την οποία κληρονομούμε. Προσέξτε, αναφερόμαστε στην αμέσως προηγούμενη κλάση από την οποία κληρονομούμε και όχι οποιαδήποτε κλάση στο δέντρο κληρονομικότητας το οποίο ίσως αποτελείται από πολλαπλές κλάσεις.
Με αυτή την λογική λοιπόν μπορούμε να αλλάξουμε τον κώδικα της payment μεθόδου μέσα στην κλάση Manager ως εξής:
Manager.java
Τώρα έχουμε την δυνατότητα να χρησιμοποιήσουμε αυτούσιο τον κώδικα της μεθόδου από την προηγούμενη κλάση την οποία κληρονομούμε και απλά να προσθέσουμε τον έξτρα κώδικα που χρειαζόμαστε. Δεν χρειάζεται να κάνετε καμία αλλαγή στην EmployeeDemo κλάση και το αποτέλεσμα θα είναι ακριβώς το ίδιο.
Μην ξεχάσετε να κάνετε ένα μικρό donation έτσι ώστε αυτό το blog να μεγαλώσει ακόμα πιο πολύ και να έχει περισσότερες δυνατότητες στην online παράδοση δωρεάν μαθημάτων.
1 Comments
μπράβο σου για αυτήν την προσπάθεια.
ReplyDeleteθα σου πρότεινα μία σχεδόν ασήμαντη διόρθωση:
- συνήθως χρησιμοποιούμε ρήματα στις μεθόδους, διότι κάθε μέθοδος εκφράζεται ως μία ενέργεια. Για αυτόν τον λόγο συνήθως έχουμε τους "getters" και "setters" σε μία κλάση.
Πιστεύω θα ήταν καλύερα αν στο παράδειγμα είχαμε είτε την μέθοδος "getPayment()" είτε "calculatePayment()" από το σκέτο "payment" που υποδεικνύει περισσότερο property μίας κλάσης
Η γνώμη σας είναι σημαντική.