5. Αντικείμενα και κλάσεις

Σχετικά έγγραφα
Εισαγωγή στον Αντικειμενοστρεφή Προγραμματισμό Διάλεξη #2

public void printstatement() { System.out.println("Employee: " + name + " with salary: " + salary);

Αντικειμενοστρεφής Προγραμματισμός

Κλάσεις και Αντικείµενα

Εισαγωγή στον Προγραµµατισµό, Αντώνιος Συµβώνης, ΣΕΜΦΕ, ΕΜΠ,, Slide 6

2 Ορισμός Κλάσεων. Παράδειγμα: Μηχανή για Εισιτήρια. Δομή μιας Κλάσης. Ο Σκελετός της Κλάσης για τη Μηχανή. Ορισμός Πεδίων 4/3/2008

Εισαγωγή σε αντικειμενοστραφή concepts. Και λίγη C#

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Μέθοδοι

3 Αλληλεπίδραση Αντικειμένων

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Constructors, equals, tostring

2.1 Αντικειµενοστρεφής προγραµµατισµός

Κλήση Συναρτήσεων ΚΛΗΣΗ ΣΥΝΑΡΤΗΣΕΩΝ. Γεώργιος Παπαϊωάννου ( )

2.1. Εντολές Σχόλια Τύποι Δεδομένων

Οντοκεντρικός Προγραμματισμός

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Μέθοδοι

Διαδικασιακός Προγραμματισμός

Προγραμματισμός Η/Υ (ΤΛ2007 )

Αντικειμενοστρεφής Προγραμματισμός Διάλεξη 2 : ΜΕΤΑΒΛΗΤΕΣ ΤΕΛΕΣΤΕΣ & ΕΚΦΡΑΣΕΙΣ ΕΛΕΓΧΟΣ ΡΟΗΣ

Δομημένος Προγραμματισμός (ΤΛ1006)

Το πρόγραμμα HelloWorld.java. HelloWorld. Κλάσεις και Αντικείμενα (2) Ορισμός μιας Κλάσης (1) Παύλος Εφραιμίδης pefraimi <at> ee.duth.

Ειδικά Θέματα Προγραμματισμού

Προγραμματισμός Ι. Δείκτες. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Εισαγωγή στον Αντικειμενοστρέφή Προγραμματισμό Διάλεξη #12

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Αναφορές

B. Ενσωμάτωση Ιθαγενών Μεθόδων

ΠΟΛΥΜΟΡΦΙΣΜΟΣ. 4.1 Κληρονομικότητα και Αρχή της Υποκατάστασης

Αντικειμενοστρεφής Προγραμματισμός

Αντικειµενοστρεφής Προγραµµατισµός

Διάλεξη 16-17: Πολυμορφισμός (Polymorphism) Διδάσκων: Παναγιώτης Ανδρέου

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Μέθοδοι

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Μέθοδοι

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Constructors

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Δημιουργία Κλάσεων και Αντικειμένων Constructors

Κλάσεις και αντικείμενα #include <iostream.h<

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 25/10/07

Αντικειµενοστραφής Προγραµµατισµός

Εαρινό. Ύλη εργαστηρίου, Ασκήσεις Java

Πακέτα (Packages) Φωλιασμένες ή Εσωτερικές Κλάσεις (Inner Classes) Παναγιώτης Σφέτσος, PhD

Δομημένος Προγραμματισμός

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Constructors Υπερφόρτωση Αντικείμενα ως παράμετροι

Σχεδίαση Εφαρμογών και Υπηρεσιών Διαδικτύου 7 η Διάλεξη: Σύντομη εισαγωγή στην Java

class object Database Database Item Item [sub-typing and polymorphism] MusicCD Video MusicCD Video

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αναφορές Στοίβα και Σωρός Αναφορές-Παράμετροι

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αναφορές Στοίβα και Σωρός Μνήμης Αντικείμενα ως ορίσματα

Αντικειμενοστραφής Προγραμματισμός

Διάλεξη 3: Προγραμματισμός σε JAVA I. Διδάσκων: Παναγιώτης Ανδρέου

Κλάσεις στη Java. Παύλος Εφραιμίδης. Java Κλάσεις στη Java 1

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αντικείμενα ως ορίσματα Εισαγωγή στις αναφορές

Κλάσεις στη Java. Στοίβα - Stack. Δήλωση της κλάσης. ΗκλάσηVector της Java. Ηκλάση Stack

3ο σετ σημειώσεων - Πίνακες, συμβολοσειρές, συναρτήσεις

Υπερφόρτωση τελεστών

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Δημιουργία Κλάσεων και Αντικειμένων

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Αντικειμενοστρεφής Προγραμματισμός

Εργαστήριο Java. Διδάσκουσα: Εργαστηριακοί Συνεργάτες:

Εισαγωγή στον Προγραμματισμό

Αντικείµενα. ηµιουργία και χρησιµοποίηση αντικειµένων. ηµιουργία αντικειµένων

Διαγράμματα Κλάσεων στη Σχεδίαση

Αντικειμενοστρεφής Προγραμματισμός

Γενικά (για τις γραπτές εξετάσεις)

Προγραμματισμός Η/Υ (ΤΛ2007 )

1. Ξεκινώντας. 1.1 Τι είναι η Java. PDF created with FinePrint pdffactory Pro trial version

Κλάσεις. Τροποποιητές, ιασυνδέσεις, Πακέτα. Τροποποιητές ελέγχου προσπέλασης µεταβλητών και µεθόδων

Κληρονομικότητα. Παύλος Εφραιμίδης pefraimi <at> ee.duth.gr. Java Κληρονομικότητα 1

HelloWorld. Παύλος Εφραιμίδης. Java Το πρόγραμμα HelloWorld 1

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

Βασικά της γλώσσας JAVA

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κληρονομικότητα

Δυναμικές Ιστοσελίδες Εισαγωγή στην Javascript για προγραμματισμό στην πλευρά του client

Οντοκεντρικός Προγραμματισμός

Πρόγραµµα 9.1 Πέρασµα δεδοµένων στην µνήµη

ΑΠΛΗ ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑ

Προγραμματισμός Ι. Κλάσεις και Αντικείμενα. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Προγραμματισμός ΙI (Θ)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πίνακες Κλάσεις και Αντικείμενα

2. Προσδιοριστές, δεσμευμένες λέξεις και τύποι

Δομημένος Προγραμματισμός (ΤΛ1006)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Υπερφόρτωση Αντικείμενα σαν ορίσματα

Προγράμματα με δομή Κληρονομικότητας

Παύλος Εφραιµίδης. Java. Κληρονοµικότητα

Προγραμματισμός Ι (ΗΥ120)

ΠΑΝΕΠΙΣΤΗΜΙΟ AΙΓΑIΟΥ & ΑΕΙ ΠΕΙΡΑΙΑ Τ.Τ. Τμήματα Ναυτιλίας και Επιχειρηματικών Υπηρεσιών & Μηχ. Αυτοματισμού ΤΕ. Εισαγωγή στη Python

Εισαγωγή στον Προγ/μό Η/Υ

Αντικειμενοστρέφεια. Henri Matisse, Harmony in Red, Κωστής Σαγώνας Νίκος Παπασπύρου

Κατασκευαστές. Μέθοδοι Κατασκευής (Constructors).

(Διαφάνειες Νίκου Βιδάκη)

Σύνθεση και Κληρονομικότητα

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα

1 ΕΙΣΑΓΩΓΗ. Πρωταρχικοί Τύποι

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πολυμορφισμός Αφηρημένες κλάσεις Interfaces (διεπαφές)

Κλάσεις. Κατηγορίες Αντικειµένων. Κλάσεις. Φυσικά Αντικείµενα. Χώρος = Οµάδα Φυσικών Αντικειµένων. Πρόγραµµα = Οµάδα

Διαδικασιακός Προγραμματισμός

Εισαγωγή στον Αντικειμενοστρέφή Προγραμματισμό Διάλεξη #13

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Constructors, equals, tostring Αντικείμενα ως παράμετροι

Υπερφόρτωση (Overloading) Υπέρβαση (Overriding) - Upcasting Downcasting Final classes, methods

Διάλεξη 3η: Τύποι Μεταβλητών, Τελεστές, Είσοδος/Έξοδος

Εισαγωγή στον Προγραμματισμό

Εργαστήριο 02: Προγραμματισμός με Γενικούς Τύπους (JAVA Generics) ΕΠΛ231 Δομές Δεδομένων και Αλγόριθμοι

Εισαγωγή στην γλώσσα προγραμματισμού C

ΠΛΗΡΟΦΟΡΙΚΗ ΙΙ (JAVA) 18/3/2008

Transcript:

5. Αντικείμενα και κλάσεις Ολοκληρώνοντας το κεφάλαιο αυτό θα μπορείτε: Να περιγράφετε την έννοια ενός αφηρημένου τύπου δεδομένων Να γράφετε κώδικα για να ορίσετε μία μέθοδο Να χρησιμοποιείτε τη δεσμευμένη λέξη this για πρόσβαση στα μέλη δεδομένων μέσα από μία μέθοδο Να γράφετε κώδικα που να καλεί μία μέθοδο σε συγκεκριμένο αντικείμενο Να χρησιμοποιείτε τη δεσμευμένη λέξη this για πρόσβαση στο τρέχον αντικείμενο Να περιγράφετε το αποτέλεσμα του τροποποιητή private σε μία μεταβλητή μέλος Να γράφετε μεθόδους δημιουργίας κλάσεων (class constructors) και να καλείτε συγκεκριμένες μεθόδους δημιουργίας χρησιμοποιώντας το new με ορίσματα Να περιγράφετε και να χρησιμοποιείτε υποκλάσεις Να δημιουργείτε και να χρησιμοποιείτε ετερογενείς συλλογές Να δημιουργείτε και να χρησιμοποιείτε μεθόδους που δέχονται ορίσματα γενικευμένων τύπων Να υπερβαίνετε (override) μεθόδους σε μία υποκλάση και να περιγράφετε τη ροή εκτέλεσης όταν εκτελείτε μία μέθοδο που έχετε υπερβεί Να καλείτε υπερφορτωμένες (overloaded) μεθόδους και συναρτήσεις δημιουργίας Να καλείτε μεθόδους που έχετε υπερβεί (overridden methods) και να περιγράφετε πώς επιλέγεται μία μέθοδος Να κατανοείτε τη χρήση των εντολών import για πρόσβαση σε βιβλιοθήκες. 5.1 Αφηρημένοι τύποι δεδομένων Όταν τα στοιχεία των δεδομένων συνδυάζονται σε σύνθετους τύπους δεδομένων, όπως μία ημερομηνία, μπορείτε να ορίσετε ένα πλήθος από τμήματα προγραμμάτων τα οποία δρουν συγκεκριμένα πάνω σε αυτόν τον τύπο δεδομένων. Αυτό δεν είναι μία νέα έννοια. Όταν μία γλώσσα προγραμματισμού ορίζει ένα βασικό τύπο, όπως έναν int, ορίζει και ένα πλήθος πράξεων που μπορούν να πραγματοποιηθούν σε στιγμιότυπα αυτού του τύπου, όπως πρόσθεση, αφαίρεση, πολλαπλασιασμός και διαίρεση. Σε πολλές γλώσσες προγραμματισμού, από τη στιγμή που ορίζεται ένας σύνθετος τύπος αντικειμένων ο προγραμματιστής απλά ορίζει συναρτήσεις διευκόλυνσης οι οποίες δρουν σε μεταβλητές αυτού του τύπου χωρίς να υπάρχει κάποια συσχέτιση μεταξύ κώδικα και του σύνθετου τύπου, εκτός ίσως από κάποια σύμβαση ονοματολογίας. Συνεπώς μπορεί να βρείτε μία συνάρτηση που απλά ονομάζεται tomorrow() και για την οποία καθορίζετε ότι δέχεται ως όρισμα μία μεταβλητή τύπου Date. Ορισμένες γλώσσες προγραμματισμού, συμπεριλαμβανομένης και της Java, επιτρέπουν ένα πιο στενό συσχετισμό ανάμεσα στη δήλωση του τύπου δεδομένων και τη δήλωση του κώδικα που πρόκειται να δράσει σε μεταβλητές αυτού του τύπου. Μία τέτοια συσχέτιση συχνά περιγράφεται ως αφηρημένος τύπος δεδομένων (abstract data type).

Στη Java μπορείτε να δημιουργήσετε μία συσχέτιση ανάμεσα στον τύπο Date και την πράξη tomorrow ως εξής: public class Date { private int day, month, year; public void tomorrow() { // code to increment day Στη Java μπορείτε να ονομάζεται το τμήμα του κώδικα που ονομάσατε tomorrow μέθοδο (method) αν και θα ακούσετε και τους όρους συνάρτηση μέλος (member function) και επίσης απλά συνάρτηση (function). Σημείωση Μην ανησυχείτε σχετικά με την έννοια της λέξης private στη δήλωση αυτή, θα την περιγράψουμε στη συνέχεια. Στις γλώσσες που δεν υποστηρίζουν αυτή τη συσχέτιση ανάμεσα στα δεδομένα και τον κώδικα, μπορεί να βρείτε ότι ο ορισμός της μεθόδου tomorrow καθορίζει μία συγκεκριμένη ημερομηνία που θα πρέπει να αυξηθεί κατά μία μέρα. Για παράδειγμα: void tomorrow(date d); Γλώσσες όπως οι Java που υποστηρίζουν αφηρημένους τύπους δεδομένων δημιουργούν μία πιο στενή συσχέτιση ανάμεσα στα δεδομένα και τον κώδικα. Δεν περιγράφουμε τη μέθοδο σαν να εφαρμόζεται πάνω στα δεδομένα, αλλά μάλλον σκεφτόμαστε τα δεδομένα σα να γνωρίζουν πώς μπορούν να τροποποιηθούν. Στη συνέχεια αιτούμαστε από τα δεδομένα να πραγματοποιήσουν μία πράξη στον εαυτό τους ως εξής: Date d =????; // Some initialised date object d.tommorow(); Ο συμβολισμός αυτός αντικατοπτρίζει την ιδέα ότι η συμπεριφορά πραγματοποιείται από τα δεδομένα και όχι αντίστροφα. Θυμηθείτε ότι μπορείτε να αναφέρεστε στα πεδία της κλάσης Date χρησιμοποιώντας το συμβολισμό με την τελεία. d.day Και αυτό σημαίνει «το πεδίο day του αντικειμένου Date στο οποίο αναφέρεται η μεταβλητή d». Συνεπώς, μπορούμε να διαβάσουμε το προηγούμενο παράδειγμα ως εξής «η συμπεριφορά tomorrow του αντικειμένου Date στο οποίο αναφέρεται η μεταβλητή d». Με άλλα λόγια πραγματοποίησε την πράξη tomorrow στο αντικείμενο d. Αυτή η ιδέα ότι οι μέθοδοι είναι ιδιότητα των αντικειμένων και όχι ξεχωριστές από αυτά, είναι το βασικό βήμα στη δημιουργία ενός αντικειμενοστρεφούς συστήματος. Θα ακούσετε ορισμένες φορές τον όρο μεταβίβαση μηνύματος (message passing). Αυτός χρησιμοποιείται από ορισμένες γλώσσες για να παρουσιάσουν την έννοια της διαταγής σε ένα αντικείμενο να κάνει κάτι στον εαυτό του. Στην πράξη, στις γλώσσες που χρησιμοποιούν συμβατικά αυτή την τεχνολογία αντικατοπτρίζει συχνά και τη φύση των υλοποιήσεων. 5.1.1. Ορισμός μεθόδου Στη Java, οι μέθοδοι ορίζονται χρησιμοποιώντας μία προσέγγιση που μοιάζει με αυτή που χρησιμοποιείται σε άλλες γλώσσες όπως η C και η C++. Η δήλωση έχει τη μορφή: <modifiers> <return_type> <name> (<argument_list>)

<block> Το <name> μπορεί να είναι οποιοσδήποτε επιτρεπτός προσδιοριστής, με ορισμένους περιορισμούς που βασίζονται στα ονόματα που ήδη χρησιμοποιούνται. To <return_type> δηλώνει τον τύπο της τιμής που επιστρέφει η μέθοδος. Αν η μέθοδος δεν επιστρέφει τιμή θα πρέπει να δηλωθεί ως void. Η Java είναι αυστηρή σχετικά με τις επιστρεφόμενες τιμές και αν η δήλωση δηλώνει ότι η μέθοδος επιστρέφει, έστω, έναν int, τότε αυτό πρέπει να ισχύει από όλες τις πιθανές διαδρομές επιστροφής. Το τμήμα <modifiers> μπορεί να περιέχει ένα πλήθος διαφορετικών τροποποιητών συμπεριλαμβανομένων των public, protected και private. Ο τροποποιητής προσπέλασης public δηλώνει ότι η μέθοδος μπορεί να κληθεί από άλλο κώδικα και ο private δηλώνει ότι η μέθοδος μπορεί να κληθεί μόνο από τις μεθόδους της συγκεκριμένης κλάσης. Θα δούμε τον protected στη συνέχεια. Το <argument_list> επιτρέπει τη μεταβίβαση των τιμών ορισμάτων στη μέθοδο. Τα στοιχεία στη λίστα διαχωρίζονται με κόμμα ενώ κάθε ένα από τα στοιχεία αποτελείται από έναν τύπο και έναν προσδιοριστή. Για παράδειγμα το: public void adddays(int days); οδηγεί το σώμα της μεθόδου να λάβει ένα όρισμα που δηλώνει το πλήθος των ημερών που θα προστεθούν στην τρέχουσα ημερομηνία. Στη μέθοδο, αναφερόμαστε στην τιμή με χρήση του προσδιοριστή days. 5.1.2. Μεταβίβαση «κατά τιμή» Η Java μεταβιβάζει ορίσματα μόνο «κατά τιμή» (by value): δηλαδή το όρισμα δεν μπορεί να μεταβληθεί από την καλούμενη μέθοδο. Όταν ένα στιγμιότυπο αντικειμένου μεταβιβάζεται ως όρισμα σε μία μέθοδο η τιμή του ορίσματος είναι μία αναφορά στο αντικείμενο. Τα περιεχόμενα του αντικειμένου μπορούν να μεταβληθούν στην καλούμενη μέθοδο, αλλά η αναφορά στο αντικείμενο δεν αλλάζει ποτέ. Ο ακόλουθος κώδικας παρουσιάζει το σημείο αυτό: public class PassTest { float ptvalue; public static void main (String args[]) { String str; int val; // Create an instance of the class PassTest pt = new PassTest(); // Assign the int val = 11; // Try to change it pt.changeint(val); // What is the current value?

System.out.println( Int value is: + val); // Assing the string str = new String( Hello ); // Try to change it pt.changestr(str); // What is the current value? System.out.println( Str value is: + str); // Now set the ptvalue pt.ptvalue = 101f; // Now change the value of the float // through the object reference pt.changeobjvalue(pt); // What is the current value? System.out.println( Current ptvalue is : + pt.ptvalue); // Methods to change the current values public void changeint (int value) { value = 55; public void changestr (String value) { value = new String( different ); public void changeobjvalue (PassTest ref) { ref.ptvalue = 99f; Το αποτέλεσμα θα είναι κάπως έτσι % java PassTest Int value is: 11 Str value is: Hello Current ptvalue is: 99.0 Το αντικείμενο String δεν μπορεί να αλλάξει από την changestr(), αλλά τα περιεχόμενα του αντικειμένου PassTest μπορούν να αλλάξουν.

5.1.3. Η αναφορά this Στην παραδοσιακή συνάρτηση τα δεδομένα στα οποία εφαρμόζεται αναφέρονται χρησιμοποιώντας τα ορίσματα με ονόματα (named arguments). Στη Java δεν υπάρχουν ορίσματα με ονόματα. Αντ αυτού μπορείτε να αναφέρεστε στο αντικείμενο που είναι ο στόχος της πράξης με χρήση της δεσμευμένης λέξης this. Για παράδειγμα: public class Date { private int day, month, year; public void tomorrow() { this.day = this.day + 1; // κώδικας σχετικά με την ανακύκλωση... Η Java συσχετίζει αυτόματα όλες τις μεταβλητές και αναφορές μεθόδων με τη δεσμευμένη λέξη this, συνεπώς η χρήση του σε πολλές περιπτώσεις είναι πλεονάζουσα. Ο ακόλουθος κώδικας είναι απόλυτα ισοδύναμος: public class Date { private int day, month, year; public void tomorrow() { day =day + 1; // Χωρίς this πριν το day // κώδικας σχετικά με την ανακύκλωση... Υπάρχουν όμως περιπτώσεις όπου η δεσμευμένη λέξη this δεν είναι πλεονάζουσα. Για παράδειγμα μπορεί να θέλετε να καλέσετε μία μέθοδο σε κάποια εντελώς διαφορετική κλάση και να μεταβιβάσετε το στιγμιότυπο του αντικειμένου ως όρισμα. Για παράδειγμα: Birthday bday = new Birthday (this); 5.1.4. Απόκρυψη δεδομένων Η χρήση της δεσμευμένης λέξης private στη δήλωση των day, month και year στην κλάση Date έχει ως συνέπεια ότι δεν είναι δυνατή η προσπέλαση των μελών αυτών από οποιονδήποτε κώδικα εκτός από τις μεθόδους της ίδιας της κλάσης Date. Συνεπώς, δεδομένης αυτής της δήλωσης για την κλάση Date ο ακόλουθος κώδικας δεν είναι επιτρεπτός. public class DateUser { public static void main(string args[]) { Date mydate = new Date(); mydate.day = 21 // illegal! Μπορεί να θεωρηθεί παράξενο να θέλει κάποιος επί τούτου να αποτρέπει την άμεση πρόσβαση στις μεταβλητές δεδομένων, αλλά στην πράξη έχει εν δυνάμει μεγάλα πλεονεκτήματα σχετικά με την ποιότητα του προγράμματος που χρησιμοποιεί την ίδια την κλάση Date. Εφόσον τα διακριτά στοιχεία των δεδομένων δεν είναι προσπελάσιμα, ο μόνος τρόπος για να διαβάσει ή να γράψει κανείς σε αυτά είναι μέσω μεθόδων. Συνεπώς

αν το πρόγραμμά σας απαιτεί εσωτερική συνέπεια από τα μέλη της κλάσης, αυτό μπορούν να το διαχειριστούν οι μέθοδοι της ίδιας της κλάσης. Έστω μία έκδοση της κλάσης Date που επιτρέπει την πρόσβαση στα μέλη της σε οποιονδήποτε εξωτερικό. Θα ήταν πολύ εύκολο για οποιονδήποτε να κωδικοποιήσει τα επόμενα: Date d = new Date(); d.day = 32; d.month = 2; d.day = 30; // επιτρεπτό, αλλά λάθος d.month = d.month + 1; // δεν γίνεται έλεγχος για ανακύκλωση των μηνών Προσοχή Αυτές, όπως και πλήθος άλλων αναθέσεων, οδηγούν σε μη επιτρεπτές ή μη συνεπείς τιμές στα πεδία ενός αντικειμένου Date. Μία τέτοια περίπτωση δε θα παρουσιαστεί άμεσα ως πρόβλημα (bug), αλλά είναι σίγουρο ότι σε κάποια χρονική στιγμή θα οδηγήσει το πρόβλημα σε κατάρρευση. Αν τα δεδομένα μέλη μίας κλάσης δεν είναι εκτεθειμένα, ο χρήστης της κλάσης αναγκάζεται να μεταβάλει τις μεταβλητές μέλη με χρήση των μεθόδων. Οι μέθοδοι αυτές, επειδή περιέχουν κώδικα, μπορούν να πραγματοποιούν ελέγχους εγκυρότητας. Έστω η ακόλουθη μέθοδος ως μέλος της κλάσης Date. public void setday (int targetday) { if (targetday > this.daysinmonth()) { System.err.println( invalid day + targetday); else { this.day = targetday; Η μέθοδος ελέγχει να δει αν η ημέρα που της ζητήθηκε να θέσει είναι στην πράξη έγκυρη. Αν δεν είναι αγνοεί την αίτηση και εκτυπώνει ένα μήνυμα. Θα δείτε στη συνέχεια ότι η Java παρέχει ένα πιο αποτελεσματικό μηχανισμό για την αντιμετώπιση ορισμάτων εκτός ορίων. Προς το παρόν μπορείτε να δείτε ότι η κλάση Date στην πράξη προστατεύεται από ημερομηνίες εκτός ορίων. Σημείωση Στο παράδειγμα αυτό υποθέτουμε ότι η daysinmonth() είναι μία μέθοδος της κλάσης Date. Συνεπώς έχει μία τιμή this από την οποία μπορεί να εξάγει τα πεδία month και year που απαιτούνται για να απαντήσει στην ερώτηση. Όπως και με τις μεταβλητές μέλη η χρήση του this για τον προσδιορισμό της μεθόδου daysinmonth() είναι πλεονάζουσα σε αυτή την περίπτωση. Οι κανόνες που σχετικά με το πώς είναι ο ορθός τρόπος κλήσης μίας μεθόδου όπως «η τιμή του ορίσματος πρέπει να είναι μέσα στο επιτρεπτό εύρος ημερών του μήνα του αντικειμένου» ονομάζονται προσυνθήκες (preconditions). Η προσεκτική χρήση των ελέγχων προσυνθηκών μπορεί να κάνει μία κλάση ευκολότερη στην επαναχρησιμοποίηση της και πολύ πιο αξιόπιστη στην περίπτωση αυτή, καθώς ο προγραμματιστής που χρησιμοποιεί την κλάση θα μπορεί να βρει άμεσα αν κάποια μέθοδος δεν χρησιμοποιείται με τον ορθό τρόπο.

5.1.5. Οριοθέτηση Επιπρόσθετα στην προστασία των δεδομένων ενός αντικειμένου από εσφαλμένη τροποποίηση αναγκάζοντας το χρήστη να προσπελαύνει τα δεδομένα μέσω μίας μεθόδου επιτρέπουμε στην κλάση να επαναχρησιμοποιείται πιο απλά φροντίζοντας ώστε οι απαιτούμενες παρενέργειες να αντιμετωπίζονται κατάλληλα. Στην περίπτωση της κλάσης Date, για παράδειγμα, θεωρήστε πώς θα έπρεπε να δομηθεί η μέθοδος tomorrow. Αν τα δεδομένα ήταν προσπελάσιμα από οποιονδήποτε κάθε χρήστης της κλάσης θα έπρεπε να αυξάνει την τιμή της ημέρας, να την ελέγχει σε σχέση με το πλήθος των ημερών του τρέχοντος μήνα και να χειρίζεται κατάλληλα το τέλος του μήνα (και πιθανώς το τέλος του έτους) όπου η αύξηση της ημέρας έχει ως αποτέλεσμα και αλλαγή του μήνα και πιθανά και του έτους. Αυτό είναι δύσκολο και μπορεί να προκαλέσει προβλήματα. Αν και οι ανάγκες αυτές είναι καλά κατανοητές για ημερομηνίες, άλλοι τύποι δεδομένων μπορεί να έχουν παρόμοια προβλήματα τα οποία δεν είναι τόσο καλά τεκμηριωμένα. Αναγκάζοντας το χρήστη της κλάσης να χρησιμοποιήσει την παρεχόμενη μέθοδο tomorrow() όλοι μπορούν να είναι σίγουροι ότι οι απαιτούμενες παρενέργειες θα αντιμετωπιστούν με συνέπεια και ορθότητα κάθε φορά. Αυτή η άποψη της απόκρυψης δεδομένων αναφέρεται γενικά ως οριοθέτηση (encapsulation). 5.2 Υπερφόρτωση (overloading) ονομάτων μεθόδων Σε ορισμένες περιπτώσεις μπορεί να θέλετε να γράψετε αρκετές μεθόδους στην ίδια κλάση οι οποίες θα πραγματοποιούν ουσιαστικά την ίδια εργασία, αλλά με διαφορετικά ορίσματα. Έστω μία απλή μέθοδος η οποία έχει ως σκοπό της να παρουσιάζει μία αναπαράσταση σε μορφή κειμένου του ορίσματός της. Η μέθοδος αυτή μπορεί να ονομάζεται print(). Έστω τώρα ότι θέλετε μία διαφορετική μέθοδο εκτύπωσης για την εκτύπωση των τύπων int, float και String. Αυτό είναι λογικό, καθώς οι διαφορετικοί τύποι απαιτούν διαφορετική μορφοποίηση και πιθανά διαφορετικό χειρισμό. Μπορείτε να δημιουργήσετε τρεις μεθόδους που θα ονομάσετε printint(), printfloat() και printstring(), αντίστοιχα. Αλλά αυτό μπορεί να οδηγήσει σε προβλήματα. Η Java, όπως και πολλές άλλες γλώσσες, σάς επιτρέπει την επαναχρησιμοποίηση ενός ονόματος μεθόδου για περισσότερες από μία μεθόδους. Προφανώς αυτό μπορεί να λειτουργήσει αν υπάρχει κάτι στις συνθήκες υπό τις οποίες γίνεται η κλήση που θα μας επιτρέπει να διακρίνουμε που είναι η μέθοδος που χρειαζόμαστε στην πράξη. Στην περίπτωση των τριών μεθόδων εκτύπωσης είναι δυνατό να κάνουμε τη διάκριση αυτή με βάση τα ορίσματα. Επαναχρησιμοποιώντας το όνομα της μεθόδου καταλήγουμε σε τρεις μεθόδους ως εξής: public void print(int i) public void print(float f) public void print(string s) Όταν γράφετε κώδικα που καλεί μία από αυτές τις μεθόδους επιλέγεται η κατάλληλη ανάλογα με τον τύπο του ορίσματος ή των ορισμάτων που παρέχετε. Για τις υπερφορτωμένες μεθόδους υπάρχουν δύο κανόνες που πρέπει να ισχύουν:

Οι λίστες των ορισμάτων των εντολών που κάνουν την κλήση πρέπει να διαφέρουν επαρκώς ώστε να επιτρέπουν τον αναμφισβήτητο καθορισμό του ποια είναι η κατάλληλη μέθοδος προς κλήση. Καθώς είναι επιτρεπτές κάποιες προαγωγές (π.χ. float -> double) αυτό μπορεί να προκαλέσει σύγχυση σε ορισμένες περιπτώσεις. Ο τύπος επιστροφής των μεθόδων μπορεί να είναι διαφορετικός, αλλά αυτό δεν είναι επαρκές ώστε να είναι η μόνη διαφορά ο τύπος επιστροφής. Πρέπει να διαφέρει η λίστα των ορισμάτων των διαφορετικών υπερφορτώσεων. 5.3 Δημιουργία και αρχικοποίηση αντικειμένων Μέχρι τώρα έχουμε δει ότι εκτελώντας μία κλήση στο new Xxxx() μπορούμε να δεσμεύσουμε μνήμη για το νέο αντικείμενο. Επιπρόσθετα έχουμε δει ότι σε ορισμένες περιπτώσεις μπορούμε να έχουμε ορίσματα μέσα σε παρενθέσεις, για παράδειγμα new Button( Press me ). Η κλήση της μεθόδου δημιουργίας (constructor) προκαλεί τα ακόλουθα: 1. Πρώτον, δεσμεύεται χώρος για το νέο αντικείμενο και γίνονται οι εξ ορισμού αρχικοποιήσεις. Στη Java η φάση αυτή είναι ατομική ώστε να βεβαιωθούμε ότι δεν πρόκειται να λάβουμε ένα αντικείμενο στο οποίο να υπάρχουν τυχαίες αρχικές τιμές. 2. Στη συνέχεια πραγματοποιούνται τυχόν ρητές αρχικοποιήσεις. 3. Τέλος, εκτελείται μία συνάρτηση δημιουργίας, η οποία μοιάζει πάρα πολύ με μία ειδική μέθοδο. Το υποκεφάλαιο αυτό εξετάζει τις δύο τελευταίες φάσεις. 5.3.1. Ρητή αρχικοποίηση μελών Αν τοποθετήσετε απλές εκφράσεις ανάθεσης στις δηλώσεις των μελών μίας κλάσης, μπορείτε να έχετε ρητές αρχικοποίησης των μελών κατά τη δημιουργία του αντικειμένου. public class Initialized { private int x = 5; private String name = Fred ; private Date created = new Date(); // Accessor methods go here... 5.3.2. Μέθοδοι δημιουργίας συναρτήσεων Ο μηχανισμός ρητής αρχικοποίησης που μόλις περιγράψαμε παρέχει έναν απλό τρόπο για να θέσετε τις αρχικές τιμές σε ένα αντικείμενο. Ορισμένες φορές όμως μπορεί να χρειάζεται να εκτελέσετε μία μέθοδο για να πραγματοποιήσετε την αρχικοποίηση. Μπορεί να χρειάζεται να αντιμετωπίσετε πιθανές εξαιρέσεις με try/catch. Μπορεί να θέλετε να χρησιμοποιήσετε βρόχους ή υπό συνθήκη εντολές για να καθορίσετε την αρχικοποίηση. Και μπορεί να θέλετε να μεταβιβάσετε ορίσματα στη διαδικασία δημιουργίας ώστε ο κώδικας που απαιτεί τη δημιουργία ενός νέου αντικειμένου να μπορεί να ελέγξει το

αντικείμενο που δημιουργεί. Ένα παράδειγμα είναι αντικείμενα όπως τα γραφικά πλήκτρα στα οποία χρειαζόμαστε μία συμβολοσειρά που θα λειτουργήσει ως ετικέτα. Στην πράξη η τρίτη φάση στη δημιουργία ενός νέου αντικειμένου είναι μία κλήση σε μία μέθοδο αρχικοποίησης. Η μέθοδος αυτή κατά συνθήκη ονομάζεται μέθοδος δημιουργίας ή γεννήτρια (constructor), αν και η δημιουργία του αντικειμένου έχει ήδη γίνει. Για να γράψετε μία μέθοδο που να ονομάζεται συνάρτηση δημιουργίας πρέπει να ακολουθείτε τους επόμενους δύο κανόνες: 1. Το όνομα της μεθόδου πρέπει να είναι ακριβώς το ίδιο με το όνομα της κλάσης. 2. Δεν πρέπει να είναι δηλωμένος τύπος επιστροφής για τη μέθοδο. Για παράδειγμα: public class Xyz { // member variables public Xyz() { // set up the object public Xyz(int x) { // set up the object with a parameter Σημείωση Όπως και με τις μεθόδους μπορείτε να υπερφορτώσετε το όνομα της συνάρτησης δημιουργίας παρέχοντας αρκετές συναρτήσεις δημιουργίας με διαφορετικές λίστες ορισμάτων. Όταν δίνετε την κλήση new Xyz(argument_list), η λίστα των ορισμάτων καθορίζει ποια συνάρτηση δημιουργίας θα χρησιμοποιηθεί. 5.3.3. Εξ ορισμού μέθοδος δημιουργίας Έχουμε ήδη αναφέρει ότι κάθε κλάση έχει τουλάχιστον μία συνάρτηση δημιουργίας, αλλά μέχρι τώρα καμία από τις κλάσεις που περιγράψαμε δεν είχε συνάρτηση δημιουργίας. Στην πράξη, αν δεν γράψετε μία συνάρτηση δημιουργίας η Java δημιουργεί μία για εσάς. Αυτή η συνάρτηση δημιουργίας δε δέχεται ορίσματα και έχει κενό σώμα. Η εξ ορισμού συνάρτηση δημιουργίας σάς επιτρέπει να δημιουργείτε στιγμιότυπα αντικειμένων με την new Xxx(), διαφορετικά θα απαιτείτο να παρέχετε μία συνάρτηση δημιουργία για κάθε κλάση. Σημείωση - Είναι σημαντικό να κατανοήσετε ότι αν προσθέσετε μία συνάρτηση δημιουργίας με ορίσματα σε μία κλάση η οποία δεν είχε πριν κάποια συνάρτηση δημιουργίας, χάνετε την εξ ορισμού συνάρτηση δημιουργίας. Από το σημείο αυτό και μετά κλήσεις στη new Xxx() θα προκαλούν λάθη μεταγλώττισης. 5.4 Υποκλάσεις 5.4.1. Η σχέση is-a Στον προγραμματισμό συχνά δημιουργείτε ένα μοντέλο ενός πράγματος, για παράδειγμα ενός εργαζομένου, και στη συνέχεια χρειάζεστε μία περισσότερο εξειδικευμένη έκδοση

του αρχικού μοντέλου. Για παράδειγμα, μπορεί να χρειαζόμαστε ένα μοντέλο για έναν διευθυντή. Σαφώς ο διευθυντής στην πράξη είναι ένας (is-a) εργαζόμενος, αλλά είναι ένας εργαζόμενος με επιπρόσθετα χαρακτηριστικά. Οι ακόλουθες κλάσεις παρουσιάζουν ακριβώς αυτό: public class Employee { private String name; private Date hiredate; private Date dateofbirth; private String jobtitle; private int grade;... public class Manager { private String name; private Date hiredate; private Date dateofbirth; private String jobtitle; private int grade; private String department; private Employee[] subordinates;... Στο παράδειγμα αυτό υπάρχουν διπλότυπα ανάμεσα στις κλάσεις Manager και Employee. Στην πραγματικότητα θα πρέπει να υπάρχει ένα πλήθος μεθόδων που θα είναι εφαρμόσιμες στο Employee και πιθανότατα οι περισσότερες από αυτές θα είναι εφαρμόσιμες και για την κλάση Manager χωρίς μεταβολές. Συνεπώς, αυτό που χρειαζόμαστε είναι ένας τρόπος να δημιουργούμε μία νέα κλάση από μία ήδη υπάρχουσα: αυτό ονομάζεται δημιουργία υποκλάσεων. 5.4.2. Η δεσμευμένη λέξη extends Στις αντικειμενοστρεφείς γλώσσες παρέχονται ειδικοί μηχανισμοί που επιτρέπουν στον προγραμματιστή να ορίζει μια κλάση με όρους μίας προηγούμενα ορισμένης κλάσης. Αυτό επιτυγχάνεται στη Java με χρήση της δεσμευμένης λέξης extends ως εξής: public class Employee { private String name; private Date hiredate; private Date dateofbirth; private String jobtitle; private int grade;... public class Manager extends Employee{ private String department; private Employee[] subordinates;

... Με τον τρόπο αυτή η κλάση Manager ορίζεται ώστε να έχει όλες τις μεταβλητές και τις μεθόδους που έχει η κλάση Employee. Όλες οι μεταβλητές και οι μέθοδοι κληροδοτούνται από τον ορισμό της γονικής κλάσης (parent class). Το μόνο που πρέπει να κάνει ο προγραμματιστής είναι να ορίσει τα επιπρόσθετα χαρακτηριστικά ή όπως θα δούμε στη συνέχεια να καθορίσει ποιες μεταβολές πρέπει να γίνουν. Σημείωση Η προσέγγιση αποτελεί μία σημαντική βελτίωση σε ό,τι αφορά τη συντήρηση και συνεπώς και την αξιοπιστία. Αν γίνει μία διόρθωση στην κλάση Employee, η κλάση Manager διορθώνεται χωρίς να χρειάζεται να ενδιαφερθεί σχετικά ο προγραμματιστής. 5.4.3. Απλή κληρονομικότητα Η Java επιτρέπει σε μία κλάση να επεκτείνει μόνο μία άλλη κλάση. Ο περιορισμός αυτός ονομάζεται απλή κληρονομικότητα. Η συζήτηση για τα σχετικά πλεονεκτήματα της απλής και της πολλαπλής κληρονομικότητας είναι θέμα εκτεταμένων συζητήσεων ανάμεσα στους αντικειμενοστρεφείς προγραμματιστές. Η Java επιβάλλει την απλή κληρονομικότητα γιατί θεωρείται ότι προσφέρει πιο αξιόπιστο κώδικα, αν και ορισμένες φορές αυτό γίνεται κάνοντας πιο δύσκολη τη ζωή των προγραμματιστών. Στη συνέχεια θα δούμε μία διευκόλυνση που ονομάζεται διεπαφή (interface) και η οποία επιτρέπει ορισμένα από τα πλεονεκτήματα της πολλαπλής κληρονομικότητας. 5.4.4. Οι συναρτήσεις δημιουργίας δεν κληρονομούνται Είναι σημαντικό να γνωρίζουμε ότι παρ όλο που μία υποκλάση κληρονομεί όλες τις μεθόδους και τις μεταβλητές από τη γονική κλάση της, δεν κληρονομεί τις συναρτήσεις δημιουργίας. Υπάρχουν μόνο δύο τρόποι με τους οποίους μπορείτε να αποκτήσετε μία συνάρτηση δημιουργίας: είτε γράφετε μία συνάρτηση δημιουργίας, είτε επειδή δεν έχετε γράψει καμία συνάρτηση δημιουργίας, η κλάση έχει μία εξ ορισμού συνάρτηση δημιουργίας. 5.4.5. Πολυμορφισμός Περιγράφοντας ότι ο Manager είναι ένας Employee δεν είναι απλά ένας βολικός τρόπος για να περιγράψουμε τη συσχέτιση ανάμεσα στις δύο κλάσεις. Θυμηθείτε ότι έχουμε πει ότι ένας Manager λαμβάνει όλα τα χαρακτηριστικά, τόσο τα μέλη όσο και τις μεθόδους, της γονικής κλάσης Employee. Αυτό σημαίνει ότι κάθε πράξη που είναι επιτρεπτή σε ένα Employee είναι επίσης επιτρεπτή σε ένα Manager. Αν ο Employee έχει μεθόδους raisesalary() και fire() τότε το ίδιο ισχύει και για την κλάση Manager. Αυτό μας οδηγεί στην ιδέα ότι τα αντικείμενα είναι πολυμορφικά, δηλαδή έχουν «πολλές μορφές». Ένα συγκεκριμένο αντικείμενο μπορεί να έχει τη μορφή ενός Manager, αλλά επίσης έχει και τη μορφή ενός Employee. Προκύπτει ότι στη Java υπάρχει μία κλάση η οποία είναι η γονική κλάση όλων των άλλων. Αυτή είναι η κλάση java.lang.object. Συνεπώς, στην πράξη, οι προηγούμενοι ορισμοί μας ήταν απλά συντομογραφίες των public class Employee extends Object και

public class Manager extends Employee Η κλάση Object ορίζει ένα πλήθος χρήσιμων μεθόδων, συμπεριλαμβανομένης της tostring(), στην οποία οφείλεται το γεγονός ότι τα πάντα στη Java μπορούν να μετατραπούν σε αναπαράσταση συμβολοσειράς (ακόμα και αν αυτό μπορεί να είναι περιορισμένης χρήσης). Η Java, όπως και οι περισσότερες αντικειμενοστρεφείς γλώσσες μάς επιτρέπει να αναφερόμαστε σε ένα αντικείμενο χρησιμοποιώντας μία μεταβλητή που είναι τύπου της γονικής κλάσης. Συνεπώς μπορούμε να πούμε: Employee e = new Manager(); Χρησιμοποιώντας τη μεταβλητή e ως έχει μπορείτε να προσπελαύνετε μόνο εκείνα τα μέρη του αντικειμένου που αποτελούν μέρος του Employee, ενώ τα μέρη που είναι εξειδικευμένα στο Manager είναι κρυφά. Αυτό γίνεται γιατί σε ό,τι αφορά το μεταγλωττιστή η e είναι τύπου Employee και όχι Manager. 5.4.6. Ορίσματα μεθόδων και ετερογενείς συλλογές Μπορεί να μας φαίνεται μη λογικό να δημιουργούμε ένα στιγμιότυπο της κλάσης Manager και στη συνέχεια να το αναθέτουμε σε μία μεταβλητή τύπου Employee. Αυτό είναι αλήθεια, αλλά υπάρχουν λόγοι για τους οποίους μπορεί να θέλετε να πετύχετε το ίδιο αποτέλεσμα. Χρησιμοποιώντας την προσέγγιση αυτή μπορείτε να γράφετε μεθόδους που δέχονται αντικείμενα που ανήκουν σε μία «γενικευμένη» κλάση, στην περίπτωση αυτή Employee, και λειτουργούν ορθά για οποιαδήποτε υποκλάση της. Συνεπώς, μπορείτε να παράγετε μία μέθοδο σε μία κλάση εφαρμογής που δέχεται ένα εργαζόμενο και συγκρίνει το μισθό του με κάποιο όριο για να υπολογίσει τις κρατήσεις για την εφορία. Με χρήση των πολυμορφικών διευκολύνσεων αυτό γίνεται αρκετά απλά: public TaxRate findtaxrate(employee e) { // do calculations and return tax rate for e // Σε άλλο σημείο της κλάσης εφαρμογής Manager m = new Manager();... TaxRate t = findtaxrate(m); Αυτό είναι επιτρεπτό γιατί ένας Manager είναι ένας Employee. Μία ετερογενής συλλογή είναι μία συλλογή ανόμοιων πραγμάτων. Στις αντικειμενοστρεφείς γλώσσες μπορείτε να δημιουργήσετε συλλογές πραγμάτων που έχουν μία κοινή προγονική κλάση. Συνεπώς μπορείτε να έχετε το ακόλουθο: Employee [] staff = new Employee[1024]; staff[0] = new Manager(); staff[1] = new Employee(); και ούτω κάθ εξής. Μπορείτε ακόμα να γράψετε μία μέθοδο ταξινόμησης που βάζει τους εργαζόμενους κατά σειρά ηλικίας, ή κατά σειρά μισθού, χωρίς να χρειάζεται να ανησυχείτε για το γεγονός ότι ορισμένοι από αυτούς είναι διευθυντές.

Σημείωση Επειδή στη Java κάθε κλάση είναι υποκλάση της Object, μπορείτε να χρησιμοποιήσετε ένα πίνακα από Object ως περιέκτη οποιωνδήποτε αντικειμένων. Το μόνο που δεν μπορεί να προστεθεί σε ένα array of Object είναι βασικές μεταβλητές (int, float κλπ). Ακόμα καλύτερη από ένα array of Object είναι η κλάση Vector που έχει σχεδιαστεί για την αποθήκευση ετερογενών συλλογών αντικειμένων. 5.4.7. Ο τελεστής instanceof Δεδομένου του ότι μπορείτε να μεταβιβάζετε αντικείμενα με χρήση αναφορών στη γονική τους κλάση, ορισμένες φορές θέλετε να γνωρίζετε τι είναι αυτό που έχετε στην πράξη. Αυτός είναι ο σκοπός του τελεστή instanceof. Έστω ότι έχετε την πιο κάτω ιεραρχία κλάσεων: public class Employee extends Object public class Manager extends Employee public class Contractor extends Employee Σημείωση Θυμηθείτε ότι αν και είναι επιτρεπτό να γράψετε extends Object είναι πλεονάζον. Εδώ παρουσιάζεται απλά ως υπενθύμιση. Αν λάβετε ένα αντικείμενο μέσω μίας αναφοράς τύπου Employee μπορεί να προκύψει (ή να μην προκύψει) ότι είναι τύπου Manager ή Contractor. Αν ενδιαφέρεστε σχετικά μπορείτε να το ελέγξετε ως εξής χρησιμοποιώντας τον instanceof public void method(employee e) { if (e instanceof Manager) { // call him Sir else if (e instanceof Contractor) { // keep company secrets else { // plain employee, talk freely over a drink 5.4.8. Μετατροπές αντικειμένων Σε περιπτώσεις στις οποίες έχετε λάβει μία αναφορά σε μία γονική κλάση, αλλά έχετε καθορίσει με χρήση του τελεστή instanceof ότι το αντικείμενο είναι στην πράξη μίας συγκεκριμένης κλάσης μπορείτε να επαναφέρετε τη συνολική λειτουργικότητα του αντικειμένου μετατρέποντας (casting) την αναφορά. public void method(employee e) { if (e instanceof Manager) { Manager m = (Manager)e; System.out.println( Είναι ο διευθυντής του τμήματος + m.department); // υπόλοιπες πράξεις

Αν δεν κάνετε τη μετατροπή, η προσπάθειά σας να αναφερθείτε στο e.department θα αποτύχει, καθώς ο μεταγλωττιστής δεν γνωρίζει κανένα μέλος με το όνομα department στην κλάση Employee. Αν δεν κάνετε έλεγχο με χρήση του instanceof έχετε τον κίνδυνο να αποτύχει η μετατροπή. Γενικά κάθε προσπάθεια μετατροπής μίας αναφοράς αντικειμένου υπόκειται στους ακόλουθους ελέγχους: Μετατροπές προς τα πάνω στην ιεραρχία των κλάσεων είναι πάντα επιτρεπτές και στην πράξη δεν απαιτούν τον τελεστή μετατροπής (cast operator), αλλά γίνονται με απλή ανάθεση. Για μετατροπές προς τα κάτω, ο μεταγλωττιστής πρέπει να ικανοποιηθεί με το γεγονός ότι η μετατροπή είναι τουλάχιστον δυνατή. Για παράδειγμα μία προσπάθεια μετατροπής μίας αναφοράς σε Manager σε αναφορά σε Contractor είναι σαφώς μη επιτρεπτή, εφόσον ένας Contractor δεν είναι Manager. Η κλάση προς την οποία γίνεται η μετατροπή πρέπει να είναι μία υποκλάση του τρέχοντος τύπου της αναφοράς. Αν ο μεταγλωττιστής έχει επιτρέψει τη μετατροπή, τότε ο τύπος της αναφοράς ελέγχεται κατά το χρόνο εκτέλεσης. Αν αποδειχθεί ότι, ίσως επειδή είχε παραληφθεί ο έλεγχος με τον instanceof από τον πηγαίο κώδικα, το αντικείμενο δεν είναι του τύπου που απαιτείται από τη μετατροπή, τότε λαμβάνει χώρα μία εξαίρεση (Exception). Οι εξαιρέσεις είναι μία μορφή λάθους κατά την εκτέλεση και θα τις εξετάσουμε στη συνέχεια. 5.5 Υπέρβαση μεθόδων Εκτός από το να μπορούμε να πάρουμε μία υπάρχουσα κλάση και να παράγουμε μία νέα βασιζόμενοι στην παλιά, προσθέτοντας νέα χαρακτηριστικά, είναι επίσης δυνατό να τροποποιήσουμε την υπάρχουσα συμπεριφορά της γονικής κλάσης. Αν έχει οριστεί μία μέθοδος σε μία νέα κλάση τέτοια ώστε το όνομά της, ο τύπος που επιστρέφει και τα ορίσματά της να είναι ακριβώς τα ίδια με αυτά μίας μεθόδου στη γονική κλάση, τότε λέμε ότι η νέα μέθοδος υπερβαίνει (overrides) την παλιά. Σημείωση Θυμηθείτε ότι το ίδιο όνομα αλλά διαφορετική λίστα ορισμάτων είναι απλά υπερφόρτωση και αναγκάζει απλά το περιβάλλον εκτέλεσης να εξετάσει τα παρεχόμενα ορίσματα για να αποφασίσει ποια μέθοδο θα καλέσει. Έστω τα πιο κάτω δείγματα μεθόδων στις κλάσεις Employee και Manager: public class Employee { String name; int grade; public String getdetails() { return Name: + name + \n + Salary: + salary; public class Manager extends Employee{ String department;

public String getdetails() { return Name: + name + \n + Manager of + department; Πριν είπαμε ότι η κλάση Manager έχει μία μέθοδο getdetails() από τον ορισμό της καθώς κληρονομεί αυτή της κλάσης Employee. Τώρα αντικαταστήσαμε, ή κάναμε υπέρβαση της αρχικής μεθόδου και προσφέραμε μία νέα αντ αυτής. Δεδομένου του προηγούμενου παραδείγματος και του ακόλουθου σεναρίου: Employee e = new Employee(); Manager m = new Manager(); Αν ζητήσετε e.getdetails() και m.getdetails() θα καλέσετε διαφορετική συμπεριφορά. Το αντικείμενο Employee θα εκτελέσει την έκδοση της getdetails() που σχετίζεται με την κλάση Employee, και το αντικείμενο Manager θα εκτελέσει την έκδοση της getdetails() που σχετίζεται με την κλάση Manager. Αυτό που είναι λιγότερο προφανές είναι αυτό που συμβαίνει όταν έχουμε: Employee e = new Manager(); ή κάποιο παρόμοιο αποτέλεσμα, όπως ένα όρισμα γενικής μεθόδου ή ένα στοιχείο από μία ετερογενή συλλογή. Στην πράξη, και αυτό είναι ένα σημαντικό χαρακτηριστικό των αντικειμενοστρεφών γλωσσών, λαμβάνετε τη συμπεριφορά που σχετίζεται με τον πραγματικό τύπο (τον τύπο κατά το χρόνο εκτέλεσης) του αντικειμένου και όχι τον τύπο της αναφοράς (τον τύπο κατά το χρόνο μεταγλώττισης). Αυτό είναι ένα ακόμα σημαντικό χαρακτηριστικό του πολυμορφισμού και συχνά αναφέρεται ως κλήση ιδεατής μεθόδου (virtual method invocation). Στο πιο πάνω παράδειγμα η μέθοδος e.getdetail() θα επιστρέψει τα αποτελέσματα της κλάσης Manager, που είναι ο πραγματικός τύπος του e. 5.5.1. Σύγκριση της Java με άλλες γλώσσες Σημείωση Αν προγραμματίζετε σε C++ υπάρχει μία σημαντική διαφορά που πρέπει να διακρίνετε ανάμεσα στη Java και τη C++. Στη C++ επιτυγχάνετε την πιο πάνω συμπεριφορά μόνο αν δηλώσετε τη μέθοδο ως virtual στον πηγαίο κώδικα. Σε «καθαρά» αντικειμενοστρεφείς γλώσσες όμως αυτό δεν είναι φυσιολογικό. Η C++ το κάνει για να αυξήσει την ταχύτητα εκτέλεσης. Θα ακούσετε ορισμένες φορές όσους ασχολούνται με τον αντικειμενοστρεφή προγραμματισμό να αναφέρονται σε «μεταβίβαση μηνύματος». Είναι ένας βολικός τρόπος να σκεφτόμαστε την κλήση ιδεατών μεθόδων φανταζόμενοι ότι η μέθοδος είναι μία εντολή που μεταβιβάζεται στο αντικείμενο. Συνεπώς, αντί να λέμε στη CPU να εκτελέσει ένα τμήμα κώδικα, λέμε στο αντικείμενο «κάνε για μένα το xxx». Το μοντέλο αυτό κάνει εύκολα κατανοητή τη συμπεριφορά που σχετίζεται με το πραγματικό αντικείμενο. Στην πράξη, αυτό περιγράφει επίσης καλά τον τρόπο με τον οποίο υλοποιείται το σύστημα σε ορισμένες άλλες γλώσσες.

5.6 Ομαδοποίηση κλάσεων 5.6.1. Πακέτα Η Java παρέχει το μηχανισμό των πακέτων ως ένα τρόπο ομαδοποίησης σχετιζόμενων κλάσεων. Μέχρι τώρα όλα τα παραδείγματά μας αναφέρονταν στο εξ ορισμού, μη ονοματισμένο, πακέτο (package). Μπορείτε να δηλώσετε ότι οι κλάσεις σε ένα αρχείο πηγαίου κώδικα ανήκουν σε ένα συγκεκριμένο πακέτο χρησιμοποιώντας την εντολή package. // Κλάση Employee για το τμήμα Οικονομικών της εταιρίας ABC package abc.financedept; public class Employee {... Η δήλωση του πακέτου, αν υπάρχει, πρέπει να βρίσκεται στην αρχή του αρχείου πηγαίου κώδικα. Μπορεί να προηγούνται κενά ή σχόλια, αλλά τίποτε άλλο. Μόνο μία δήλωση πακέτου επιτρέπεται και αυτή ισχύει για ολόκληρο το αρχείο πηγαίου κώδικα. Τα ονόματα των πακέτων είναι ιεραρχικά και χωρίζονται με τελείες. Είναι σύνηθες τα στοιχεία ενός ονόματος πακέτου να είναι εξ ολοκλήρου πεζά, αλλά το όνομα της κλάσης θα πρέπει να ξεκινά με κεφαλαίο γράμμα και μπορείτε να χρησιμοποιήσετε και άλλα κεφαλαία γράμματα για να διαχωρίσετε τις λέξεις στο όνομα της κλάσης. Όταν χρησιμοποιείτε μία δήλωση πακέτου δε χρειάζεται να εισάγετε (import) τις κλάσεις που προέρχονται από το ίδιο πακέτο ή οποιοδήποτε άλλο στοιχείο του πακέτου. Θυμηθείτε ότι η εντολή import για να μεταφέρετε κλάσεις από άλλα πακέτα στο τρέχοντα χώρο ονομάτων. Το τρέχον πακέτο, είτε ρητά καθορισμένο είτε έμμεσα, είναι πάντα μέρος του τρέχοντος χώρου ονομάτων. 5.6.2. Η εντολή import Στη Java όταν θέλετε να χρησιμοποιήσετε τις διευκολύνσεις των πακέτων μπορείτε να χρησιμοποιήσετε την εντολή import για να πείτε στο μεταγλωττιστή που θα βρει τις κλάσεις που χρησιμοποιείτε. Στην πράξη, το όνομα του πακέτου για παράδειγμα abc.financedept αποτελεί μέρος του ονόματος της κλάσης μέσα στο πακέτο. Μπορείτε να αναφερθείτε στην κλάση Employee ως abc.financedept.employee οπουδήποτε, αλλά για να κερδίσετε χρόνο μπορείτε να δώσετε μία εντολή import και στη συνέχεια να χρησιμοποιείτε απλά το όνομα Employee import abc.financedept.*; public class Manager extends Employee { String department; Employee [] subordinates; Σημείωση Οι εντολές import πρέπει να προηγούνται όλων των δηλώσεων κλάσεων.

5.6.3. Μορφή καταλόγων και η μεταβλητή περιβάλλοντος CLASSPATH Τα πακέτα «αποθηκεύονται» σε έναν κατάλογο που δημιουργείται από το όνομα του πακέτου. Για παράδειγμα, το αρχείο Employee.class του προηγούμενου παραδείγματος θα πρέπει να βρίσκεται μετά τη μεταγλώττιση σε ένα κατάλογο path/abc/financedept. Ο κατάλογος abc που αποτελεί τη βάση της ιεραρχίας θα πρέπει να περιέχεται στην CLASSPATH. Η CLASSPATH δεν έχει χρησιμοποιηθεί μέχρι τώρα, καθώς αν δεν έχει τεθεί η μεταβλητή η εξ ορισμού συμπεριφορά των εργαλείων είναι να συμπεριλαμβάνουν τη συνήθη τοποθεσία των κλάσεων που παρέχονται και το τρέχοντα κατάλογο. Αν θέλετε να προσπελαύνετε πακέτα που βρίσκονται σε άλλα σημεία πρέπει να θέσετε ρητά τη μεταβλητή CLASSPATH. Ο μεταγλωττιστής της Java θα δημιουργήσει τον κατάλογο του πακέτου και θα μεταφέρει εκεί τα μεταγλωττισμένα αρχεία κλάσεων αν χρησιμοποιήσετε την παράμετρο -d: % javac d /home/anton/mypackages Employee.java Η μεταβλητή περιβάλλοντος CLASSPATH θα πρέπει να περιλαμβάνει τη διαδρομή του πακέτου: CLASSPATH=/home/anton/mypackages:. ώστε ο μεταγλωττιστής να μπορεί να βρει την κλάση abc.financedept.employee στο αρχείο Manager.java στο προηγούμενο παράδειγμα. 5.7 Ασκήσεις 5.7.1. Επίπεδο 1: Τραπεζικός λογαριασμός 1. Δημιουργείστε ένα σύνολο κλάσεων που ορίζουν έναν τραπεζικό λογαριασμό (Bank Account). Καθορίστε τι θα πρέπει να κάνουν οι λογαριασμοί, ποια δεδομένα πρέπει να αποθηκεύουν και ποιες μεθόδους θα πρέπει να χρησιμοποιήσετε. 2. Βεβαιωθείτε ότι χρησιμοποιείτε το κατάλληλο πακέτο για τον ορισμό της τραπέζης (Bank) 5.7.2. Επίπεδο 2: Τύποι λογαριασμών 1. Τροποποιήστε την προηγούμενη άσκηση επιπέδου 1, ώστε να μπορείτε να δημιουργήσετε μία υποκλάση του Account για τα χαρακτηριστικά του Checking Account. 2. Τα Checking Accounts θα πρέπει να παρέχουν προστασία από υπεραναλήψεις. 5.7.3. Επίπεδο 3: Υπηρεσίες λογαριασμών on-line 1. Δημιουργήστε μία απλή εφαρμογή που χρησιμοποιεί τις ασκήσεις επιπέδου 1 και επιπέδου 2 για να παρέχετε υπηρεσίες για on-line άνοιγμα λογαριασμών.