ΕΙΣΑΓΩΓΗ
Στο σημερινό δωρεάν μάθημα Java
θα εξηγήσουμε τι είναι οι Abstract classes και που μας χρησιμεύουν, πως
ορίζονται τα Abstract methods, και τι ακριβώς είναι οι Sealed classes που έχουν προστεθεί στη Java 17.
Abstract Classes
Σαν abstract
κλάση ορίζουμε εκείνη την κλάση από την οποία δεν μπορούμε να δημιουργήσουμε
αντικείμενο. Ο μόνος τρόπος για να μπορέσουμε να το πετύχουμε αυτό είναι να
κληρονομήσουμε την abstract κλάση και να κάνουμε αντικείμενο από την δική μας
κλάση. Φυσικά, αφού υπάρχει κληρονομικότητα, έχουμε πρόσβαση σε όλες τις
μεταβλητές, μεθόδους και constructors της abstract κλάσης. Απλά δεν μπορούμε να
δημιουργήσουμε αντικείμενο άμεσα από την κλάση.
Σε ποιες περιπτώσεις όμως είναι χρήσιμος ένας
τέτοιος περιορισμός? Για να καταλάβουμε την χρησιμότητα της abstract κλάσης, θα
χρειαστεί να γυρίσουμε πίσω στην απλή εφαρμογή μας με τον Employee και να
παρατηρήσουμε ποιο προσεχτικά την δομή των κλάσεων.
Employee.java
Salary.java
Αυτό που παρατηρούμε είναι ότι
ένα αντικείμενο είδος Employee δεν έχει όλες τις πληροφορίες που χρειαζόμαστε.
Η κλάση Salary έρχεται να ολοκληρώσει την πληροφορία προσθέτοντας τον μισθό του
Employee. Με άλλα λόγια, δημιουργώντας ένα αντικείμενο είδος Employee δεν μας
είναι και πολύ χρήσιμο γιατί δεν θα περιέχει τον μισθό. Επίσης, μην ξεχνάτε ότι
δεν μπορούμε να χρησιμοποιήσουμε τον πολυμορφισμό για να μετατρέψουμε
αντικείμενα Employee σε αντικείμενα Salary. Ο πολυμορφισμός ισχύει από την
κλάση που δημιουργούμε το αντικείμενο και προς τα πάνω - δηλαδή προς την κλάση
Object. Αν όμως δημιουργήσουμε ένα αντικείμενο είδος Salary τότε μπορούμε να το
χειριστούμε σαν Salary, σαν Employee ή ακόμα σαν Object. Το συμπέρασμα από αυτή
τη μικρή ανάλυση είναι ότι κλάσεις που είναι πολύ γενικές και δεν προσφέρουν
ολοκληρωμένες πληροφορίες καλό θα ήταν να είναι abstract έτσι ώστε να μην
υπάρχουν αντικείμενα δημιουργημένα από αυτές. Αν και εφόσον χρειαζόμαστε τις
πληροφορίες που προσφέρουν, τότε μπορούμε να δημιουργήσουμε δικές μας κλάσεις
που κληρονομούν από τις abstract κλάσεις και αφού προσθέσουμε τις επιπλέον
πληροφορίες που χρειαζόμαστε να δημιουργήσουμε τα αντικείμενα μας.
Πως δημιουργούμε μια abstract
κλάση? Το μόνο που έχουμε να κάνουμε είναι να προσθέσουμε την λέξη abstract
πριν από την λέξη class στον ορισμό της κλάσης. Όταν προσθέσουμε την λέξη abstract στην κλάση μας, αυτόματα
σταματάει η δυνατότητα να δημιουργούμε
αντικείμενα απευθείας από αυτή την κλάση. Ο μόνος τρόπος είναι να
δημιουργήσουμε αντικείμενα από μια άλλη κλάση που κληρονομεί από την Abstract κλάση.
Employee.java
Ο κώδικας της κλάσης Salary δεν
επηρεάζεται καθόλου και παραμένει ο ίδιος όπως τον έχουμε γράψει παραπάνω.
Παρατηρήστε ότι από την στιγμή που δημιουργούμε ένα αντικείμενο είδος Salary
έχουμε πρόσβαση σε όλες τις ιδιότητες, χαρακτηριστικά και constructor της
κλάσης Employee.
EmployeeDemo.java
Output
Employee constructor
Salary Constructor
Hello Michail
Your payment is: 384.61538461538464
Αυτός είναι ο ορισμός της
Abstract κλάσης. Αν προσπαθήσετε από περιέργεια να δημιουργήσετε αντικείμενο
απευθείας από την Employee το πρόγραμμα σας θα αποτύχει. Όμως μια abstract κλάση μπορεί να περιέχει μια
ή και περισσότερες abstract μεθόδους. Τι είναι μια abstract μέθοδος?
Abstract Methods
Ας γυρίσουμε πίσω πάλι στον κώδικα μας και ας
κάνουμε μια ακόμα παρατήρηση. Η κλάση Salary κληρονομεί από την κλάση Employee
κάποιες μεθόδους και μεταβλητές αλλά όχι την μέθοδο payment( ). Αυτή την πρόσθεσε η κλάση Salary για να κάνει ποιο
ουσιαστικό και χρήσιμο το αντικείμενο Employee. Επίσης, αν θυμάστε από
προηγούμενες ενότητες, δεν έχουμε μόνο την κλάση Salary αλλά και την κλάση
Hourly που κληρονομεί από την Employee και που υπολογίζει τον μισθό ενός
εξωτερικού συνεργάτη ανάλογα με τις ώρες που δούλεψε. Και στις δύο περιπτώσεις
αφήσαμε την λογική αυτή να είναι προαιρετική – δηλαδή η κλάση Salary και η
κλάση Hourly θεώρησαν χρήσιμο να προσθέσουν την μέθοδο payment( ) στο κώδικα
τους. Δεν τους το απαίτησε κανείς. Θα μπορούσε ένας από αυτούς ή και οι δύο να
είχαν θεωρήσει σημαντική κάποια άλλη πληροφορία και όχι τον μισθό. Το επιθυμητό
θα ήταν η κλάση Employee να “απαιτούσε” σε όσους κληρονομούν από αυτήν να
έγραφαν κώδικα για συγκεκριμένες μεθόδους. Επειδή η υλοποίηση μπορεί να αλλάξει
(π.χ Hourly ή Salary) θα πρέπει η Employee να περάσει απλώς την γενική δομή της
μεθόδου (signature) και όποια κλάση κληρονομεί από την Employee να κάνει
override την συγκεκριμένη μέθοδο (ή μεθόδους) με τον δικό της κώδικα. Αυτή η
διαδικασία όμως δεν θα πρέπει να είναι προαιρετική. Με άλλα λόγια, θα πρέπει
αναγκαστικά η κλάση που κληρονομεί από την Employee να κάνει override την
μέθοδο ή τις μεθόδους που απαιτεί η Employee. Ο τρόπος λοιπόν που μπορούμε να
απαιτήσουμε μια τέτοια διαδικασία είναι να δημιουργήσουμε abstract μεθόδους.
Πως ορίζουμε μια abstract μέθοδο? Απλά
γράφουμε το signature της μεθόδου χωρίς τα άγκιστρα και αφού έχουμε προσθέσει
την λέξη abstract πριν από το return type της μεθόδου. Ας δούμε λοιπόν πως
αλλάζει ο κώδικας της Employee αφού προσθέσουμε την abstract μέθοδο payment( ).
Employee.java
Έχουμε ορίσει λοιπόν μια μέθοδο
payment( ) που επιστρέφει double και είναι abstract. Ξανά, παρατηρήστε ότι
λείπουν τα άγκιστρα. Η κλάση ή οι κλάσεις που θα κληρονομήσουν από την Employee
θα πρέπει αναγκαστικά να κάνουν override την μέθοδο payment( ) και να γράψουν
κώδικα για αυτήν. Αν δεν το κάνουν, τότε θα πρέπει να δηλώσουν και αυτές τον
εαυτό τους σαν abstract που σημαίνει ότι ούτε από αυτές τις κλάσεις θα μπορέσουμε
να κάνουμε αντικείμενο. Λογικά, κάποιος από όλο το δέντρο της κληρονομικότητας
θα γράψει τον κώδικα της μεθόδου και θα μπορούμε έτσι να δημιουργήσουμε
αντικείμενο.
Στο παράδειγμα μας, η κλάση Salary ήδη
περιέχει κώδικα για την μέθοδο payment αλλά αυτό δεν είναι προαιρετικό πια.
Πρέπει να γράψει τον κώδικα για την payment αφού κληρονομεί από την Employee.
Αν τώρα υπήρχαν περισσότερες μέθοδοι στην Employee η Salary θα έπρεπε να τις
κάνει override όλες. Αν δεν το κάνει έστω και για μια μέθοδο τότε θα πρέπει να
δηλώσει και αυτή τον εαυτό της σαν abstract.
Salary.java
EmployeeDemo.java
Output
Employee constructor
Salary Constructor
Hello Michail
Your payment is: 384.61538461538464
Αφού έχετε καταλάβει τώρα τι ακριβώς είναι
μια abstract μέθοδο, ας βάλουμε σε μορφή σύντομης λίστας την θεωρία γύρω από
τις abstract κλάσεις και τις abstract μεθόδους
1. Μπορούμε να έχουμε abstract
κλάσεις χωρίς να περιέχουν abstract μεθόδους
2. Όποια κλάση κληρονομεί από
μια abstract μέθοδο θα πρέπει να γράψει κώδικα για τις abstract μεθόδους που
κληρονομεί ειδάλλως πρέπει να δηλωθεί και αυτή σαν abstract.
3. Δεν μπορούμε να
δημιουργήσουμε αντικείμενα από μια abstract κλάση. Αλλά μπορούμε να έχουμε
πρόσβαση στις μεθόδους μιας abstract κλάσης λόγω πολυμορφισμού.
4. Μια abstract κλάση δεν
μπορεί να δηλωθεί σαν final. Γιατί δεν θα μπορούμε ούτε να δημιουργήσουμε
αντικείμενα αλλά ούτε και να κληρονομήσουμε από αυτήν.
5. Μια abstract κλάση δεν
μπορεί να έχει δηλώσει σαν private όλους τους constructors της. Ειδάλλως δεν θα
μπορούμε να κληρονομήσουμε.
6. Μια abstract μέθοδο δεν
μπορεί να δηλωθεί σαν static
7. Μια abstract μέθοδο δεν
μπορεί να δηλωθεί σαν private.
Υπάρχουν και κάποιες άλλες περιπτώσεις οι
οποίες είναι πολύ εξειδικευμένες και νομίζω ότι δεν θα τις αντιμετωπίσετε ποτέ.
Για παράδειγμα, ενώ κληρονομείτε από μια κλάση μια κανονική μέθοδο, εσείς την
κάνετε override με μια abstract μέθοδο. Αυτό σημαίνει όποιος κληρονομήσει από
εσάς θα πρέπει αναγκαστικά να γράψει κώδικα για αυτήν την μέθοδο.
Νομίζω ότι καλύψαμε αρκετά γύρω από την
έννοια του abstraction και είμαι σίγουρος ότι σιγά σιγά θα δείτε την
χρησιμότητα του ειδικότερα όταν κάνετε software design.
Sealed Class
Πριν κλείσουμε το σημερινό δωρεάν
μάθημα Java, ας αναφερθούμε και σε μια καινούργια ιδιότητα που
προστέθηκε στην Java 17 και ονομάζεται Sealed Class. Με την ιδιότητα της Sealed Class μπορούμε να ορίσουμε σε ποιες
κλάσεις επιτρέπουμε να κληρονομήσουν από την κλάση που έχουμε ορίσει σαν Sealed. Οπότε σε συνδυασμό με την abstract ιδιότητα, αν συνδυάσουμε και τις δύο
ιδιότητες τότε δεν επιτρέπουμε άμεση δημιουργία αντικειμένου, αλλά μόνο μέσω
κληρονομικότητας, και ταυτόχρονα θα πρέπει να επιτρέπεται στην συγκεκριμένη
κλάση να κληρονομήσει από την abstract.
Για να δηλώσουμε μια κλάση σαν Sealed, πρέπει να χρησιμοποιήσουμε την λέξη sealed αμέσως μετά από την abstract και να προσθέσουμε επίσης τη
λίστα με τις κλάσεις που επιτρέπονται να μας κληρονομήσουν με την λέξη permits. Τέλος, η κλάση που θα κληρονομήσει θα πρέπει να δηλωθεί
σαν non-sealed.
Employee.java
Salary.java
EmployeeDemo.java
Output
Employee constructor
Salary Constructor
Hello Michail
Your payment is:
384.61538461538464
Μην ξεχάσετε να κάνετε ένα μικρό donation έτσι ώστε αυτό το blog να μεγαλώσει ακόμα πιο πολύ και να έχει περισσότερες δυνατότητες στην online παράδοση δωρεάν μαθημάτων.
full-width
0 Comments
Η γνώμη σας είναι σημαντική.