Γλώσσες Προγραμματισμού II

256
Γλώσσες Προγραµµατισµού II (Aντικειµενοστρεφής Προγραµµατισµός)

Transcript of Γλώσσες Προγραμματισμού II

Page 1: Γλώσσες Προγραμματισμού II

Γλώσσες Προγραµµατισµού II

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

Page 2: Γλώσσες Προγραμματισμού II
Page 3: Γλώσσες Προγραμματισμού II

ΕΛΛΗΝΙΚΟ ΑΝΟΙΚΤΟ ΠΑΝΕΠΙΣΤΗΜΙΟ

Σχολή Θετικών Επιστηµών και Τεχνολογίας

Πρόγραµµα Σπουδών

ΠΛHPOΦOPIKH

Θεµατική Ενότητα

ΣΧΕ∆ΙΑΣΜΟΣ ΛΟΓΙΣΜΙΚΟΥ

Τόµος Γ'

Γλώσσες Προγραµµατισµού II(Aντικειµενοστρεφής Προγραµµατισµός)

KΛΕΑΝΘΗΣ ΘΡΑΜΠΟΥΛΙ∆ΗΣ

Eπίκουρος Kαθηγητής Tµήµατος Hλεκτρολόγων Mηχανικών & Tεχνολογίας Yπολογιστών

Πανεπιστηµίου Πατρών

ΠATPA 2001

Page 4: Γλώσσες Προγραμματισμού II

ΕΛΛΗΝΙΚΟ ΑΝΟΙΚΤΟ ΠΑΝΕΠΙΣΤΗΜΙΟ

Σχολή Θετικών Επιστηµών και Τεχνολογίας

Πρόγραµµα Σπουδών

ΠΛHPOΦOPIKH

Θεµατική Ενότητα

ΣΧΕ∆ΙΑΣΜΟΣ ΛΟΓΙΣΜΙΚΟΥ

Τόµος Γ'

Γλώσσες Προγραµµατισµού II

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

Συγγραφή

KΛΕΑΝΘΗΣ ΘΡΑΜΠΟΥΛΙ∆ΗΣ

Eπίκουρος Kαθηγητής Tµήµατος Hλεκτρολόγων Mηχανικών & Tεχνολογίας Yπολογιστών

Πανεπιστηµίου Πατρών

Κριτική Ανάγνωση

OMHPOΣ PAΓΓOΣ

Λέκτορας Tµήµατος Mαθηµατικών Πανεπιστηµίου Πατρών

Ακαδηµαϊκός Υπεύθυνος για την επιστηµονική επιµέλεια του τόµου

ΣΩKPATHΣ KATΣIKAΣ

Καθηγητής Tµήµατος Mαθηµατικών Πανεπιστηµίου Aιγαίου

Επιµέλεια στη µέθοδο της εκπαίδευσης από απόσταση

ΓEPAΣIMOΣ MΩPAΪTHΣ

Γλωσσική Επιµέλεια

BAΣIΛIKH ∆HMHTPOΠOYΛOY

Τεχνική Επιµέλεια

ΕΣΠΙ ΕΚ∆ΟΤΙΚΗ Ε.Π.Ε.

Καλλιτεχνική Επιµέλεια – Σελιδοποίηση

TYPORAMA

Συντονισµός ανάπτυξης εκπαιδευτικού υλικού και γενική επιµέλεια των εκδόσεων

ΟΜΑ∆Α ΕΚΤΕΛΕΣΗΣ ΕΡΓΟΥ ΕΑΠ / 1997–2001

ISBN: 960–538–174–5

Kωδικός Έκδοσης: ΠΛH 24/3

Copyright 2000 για την Ελλάδα και όλο τον κόσµο

ΕΛΛΗΝΙΚΟ ΑΝΟΙΚΤΟ ΠΑΝΕΠΙΣΤΗΜΙΟ

Οδός Παπαφλέσσα & Υψηλάντη, 26222 Πάτρα – Τηλ: (0610) 314094, 314206 Φαξ: (0610) 317244

Σύµφωνα µε το Ν. 2121/1993, απαγορεύεται η συνολική ή αποσπασµατική αναδηµοσίευση του βιβλίου αυτού

ή η αναπαραγωγή του µε οποιοδήποτε µέσο χωρίς την άδεια του εκδότη.

Page 5: Γλώσσες Προγραμματισμού II

¶ÂÚȯfiÌÂÓ·

K ∂ º ∞ § ∞ π √ 1

B·ÛÈΤ˜ ŒÓÓÔȘ Ù˘ AÓÙÈÎÂÈÌÂÓÔÛÙÚÂÊÔ‡˜ ÚÔÛ¤ÁÁÈÛ˘

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις ................................................................................................................. 11

1.1 Aντικείµενο – Kλάση – Στιγµιότυπο ........................................................................ 13

1.2 Τo σύστηµα στην AΠ ............................................................................................................. 16

1.3 ∆ηµιουργία – Kαταστροφή αντικειµένου ............................................................. 19

1.4 Aντικειµενοστρεφής προσέγγιση ανάπτυξης συστηµάτων

λογισµικού ....................................................................................................................................... 19

Σύνοψη ................................................................................................................................................................ 22

Bιβλιογραφία .................................................................................................................................................. 22

K ∂ º ∞ § ∞ π √ 2

EÈÛ·ÁˆÁ‹ ÛÙË Java

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις ................................................................................................................. 25

2.1 Iστορία της Java .......................................................................................................................... 26

2.2 ∆ιαδικασία ανάπτυξης προγράµµατος Java ........................................................ 28

2.2.1 ∆ιαδικασία ανάπτυξης αυτόνοµης εφαρµογής ................................... 29

2.2.2 ∆ιαδικασία ανάπτυξης Applet .......................................................................... 32

2.2.3 H εξήγηση ενός απλού Applet ......................................................................... 35

Σύνοψη ................................................................................................................................................................ 39

Bιβλιογραφία .................................................................................................................................................. 39

K ∂ º ∞ § ∞ π √ 3

KÏ¿ÛË Î·È AÓÙÈΛÌÂÓÔ

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις ................................................................................................................. 41

3.1 Γιατί κλάση και στιγµιότυπο; .......................................................................................... 43

3.2 H κλάση στην Java ................................................................................................................... 46

3.2.1 ∆ήλωση κλάσης.............................................................................................................. 46

3.2.2 ∆ηµιουργία στιγµιότυπου....................................................................................... 47

3.2.3 Πέρασµα µηνυµάτων ................................................................................................. 48

3.2.4 Προσπέλαση στα δεδοµένα αντικειµένου................................................ 49

Page 6: Γλώσσες Προγραμματισμού II

6 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

3.2.5 Ενθυλάκωση ...................................................................................................................... 50

3.3 ∆ηµιουργοί αντικειµένων..................................................................................................... 53

3.3.1 Μηχανισµός δηµιουργίας στιγµιότυπου.................................................... 53

3.3.2 Ορισµός δηµιουργού .................................................................................................. 53

3.3.3 Πολλαπλοί δηµιουργοί ............................................................................................. 55

3.3.4 Υπερφόρτωση µεθόδων........................................................................................... 56

3.3.5 Απλοποιηµένη συγγραφή δηµιουργών....................................................... 57

3.4 Mεταβλητές και µέθοδοι κλάσης................................................................................... 58

3.4.1 Μεταβλητές κλάσης.................................................................................................... 60

3.4.2 Σταθερή Κλάσης ............................................................................................................ 62

3.4.3 Μέθοδοι κλάσης............................................................................................................. 63

Σύνοψη ................................................................................................................................................................ 66

Bιβλιογραφία .................................................................................................................................................. 68

K ∂ º ∞ § ∞ π √ 4

H Java Û·Ó Â¤ÎÙ·ÛË Ù˘ C

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις ................................................................................................................. 69

4.1 Tύποι δεδοµένων ........................................................................................................................ 70

4.1.1 O τύπος Boolean ........................................................................................................... 70

4.1.2 Τύπος δείκτη .................................................................................................................... 71

4.1.3 Τύποι αναφοράς ............................................................................................................ 71

4.1.4 Τύπος πίνακα ................................................................................................................... 73

4.1.5 Αλφαριθµητικά .............................................................................................................. 74

4.2 Tελεστές ............................................................................................................................................. 75

4.3 Προτάσεις ελέγχου ροής προγράµµατος ............................................................... 76

4.3.1 Προτάσεις if/else, while και do/while ........................................................ 76

4.3.2 H πρόταση switch ........................................................................................................ 77

4.3.3 Η πρόταση for ................................................................................................................. 77

4.3.4 Οι προτάσεις break και continue .................................................................... 78

4.3.5 Η πρόταση goto ............................................................................................................. 79

4.4 Λοιπές διαφορές της Java από την C ........................................................................ 79

Σύνοψη ................................................................................................................................................................ 80

Bιβλιογραφία .................................................................................................................................................. 81

Page 7: Γλώσσες Προγραμματισμού II

K ∂ º ∞ § ∞ π √ 5

H KÏ¿ÛË Û·Ó ¢ÔÌÈÎfi ™ÙÔÈ¯Â›Ô ÙÔ˘ ¶ÚÔÁÚ¿ÌÌ·ÙÔ˜

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις ................................................................................................................. 83

5.1 Oι κλάσεις δεν είναι ανεξάρτητες µεταξύ τους ................................................ 85

5.1.1 Σχέσεις αντικειµένων ............................................................................................... 85

5.1.2 Συσχετίσεις µεταξύ κλάσεων ............................................................................ 87

5.2 Προσδιοριστές ορατότητας ............................................................................................... 91

5.3 Kατηγορίες κλάσεων .............................................................................................................. 93

5.3.1 Κλάσεις δηλωµένες σε εµβέλεια πακέτου ............................................. 94

5.3.2 Ένθετες κλάσεις ............................................................................................................ 95

Σύνοψη ................................................................................................................................................................ 97

Bιβλιογραφία .................................................................................................................................................. 98

K ∂ º ∞ § ∞ π √ 6

KÏËÚÔÓÔÌÈÎfiÙËÙ·

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις ................................................................................................................. 99

6.1 Απλή κληρονοµικότητα ..................................................................................................... 101

6.1.1 Γενικά ................................................................................................................................. 101

6.1.2 Προσθήκη νέας κλάσης ....................................................................................... 102

6.2 Πολλαπλή κληρονοµικότητα ........................................................................................ 104

6.3 Πολυµορφισµός ........................................................................................................................ 104

6.4 H κληρονοµικότητα στη Java ....................................................................................... 108

6.4.1 Ορισµός απόγονης κλάσης ............................................................................... 109

6.4.2 Αφηρηµένες κλάσεις .............................................................................................. 110

6.4.3 Κάθε κλάση έχει µια πρόγονο κλάση ...................................................... 111

6.4.4 Οι δηµιουργοί στην κληρονοµικότητα ................................................... 112

6.4.5 Επικαλυπτόµενες µεταβλητές ........................................................................ 114

6.4.6 Υπερκάλυψη µεθόδων .......................................................................................... 115

6.4.7 Interfaces .......................................................................................................................... 119

Σύνοψη ενότητας ...................................................................................................................................... 123

Σύνοψη ............................................................................................................................................................. 124

Bιβλιογραφία ............................................................................................................................................... 125

7¶ E P I E X O M E N A

Page 8: Γλώσσες Προγραμματισμού II

8 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

K ∂ º ∞ § ∞ π √ 7

AÓ¿Ù˘ÍË AÓÙÈÎÂÈÌÂÓÔÛÙÚÂÊÔ‡˜ EÊ·ÚÌÔÁ‹˜

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις .............................................................................................................. 127

7.1 Αναγνώριση Αντικειµένων ............................................................................................. 129

7.2 Ορισµός βασικών λειτουργιών ................................................................................... 129

7.3 ∆ηµιουργία πρώτης έκδοσης του προγράµµατος

της αριθµοµηχανής ................................................................................................................ 132

7.4 Ολοκλήρωση της κλάσης Operand ......................................................................... 133

7.5 Ανάπτυξη γραφικής διεπαφής (GUI) µε τον χρήστη ............................... 135

7.6 Ανταλλαγή µηνυµάτων µεταξύ µηχανής και αντικειµένων

διεπαφής .......................................................................................................................................... 136

Σύνοψη ............................................................................................................................................................. 139

Bιβλιογραφία ............................................................................................................................................... 139

K ∂ º ∞ § ∞ π √ 8

XÂÈÚÈÛÌfi˜ EÍ·ÈÚ¤ÛˆÓ

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις .............................................................................................................. 141

8.1 H έννοια του χειρισµού εξαιρέσεων ....................................................................... 144

8.2 Xειρισµός εξαιρέσεων στην Java .............................................................................. 147

8.2.1 Βασικές έννοιες .......................................................................................................... 147

8.2.2 Η κατασκευή try/catch/finally ....................................................................... 149

8.2.3 Προσθέτοντας χειρισµό εξαιρέσεων ........................................................ 152

8.2.4 ∆ήλωση τύπων εξαίρεσης ................................................................................. 154

8.2.5 Έγερση εξαίρεσης .................................................................................................... 155

Σύνοψη ............................................................................................................................................................. 158

Bιβλιογραφία ............................................................................................................................................... 159

K ∂ º ∞ § ∞ π √ 9

T·˘Ùfi¯ÚÔÓÔ˜ ¶ÚÔÁÚ·ÌÌ·ÙÈÛÌfi˜

Σκοπός, Προσδοκώµενα αποτελέσµατα, Έννοιες κλειδιάEισαγωγικές παρατηρήσεις .............................................................................................................. 161

9.1 Bασικές έννοιες ταυτόχρονου προγραµµατισµού ...................................... 164

9.2 Yποστήριξη ταυτόχρονου προγραµµατισµού από την Java .............. 166

Page 9: Γλώσσες Προγραμματισμού II

9.2.1 Η κλάση Thread ......................................................................................................... 168

9.2.2 Κύκλος ζωής ενός νήµατος .............................................................................. 170

9.2.3 Συγχρονισµός νηµάτων ....................................................................................... 172

9.2.4 Οι µέθοδοι wait και notify ................................................................................ 173

Σύνοψη ενότητας ...................................................................................................................................... 174

9.3 Λύση στο πρόβληµα παραγωγού–καταναλωτή ............................................ 174

9.3.1 Αντιµετώπιση χωρίς συγχρονισµό ............................................................. 175

9.3.2 Aντιµετώπιση µε συγχρονισµό ..................................................................... 176

Σύνοψη ............................................................................................................................................................. 177

Bιβλιογραφία ............................................................................................................................................... 178

Aπαντήσεις ασκήσεων αυτοαξιολόγησης ......................................................................... 179

Eνδεικτικές απαντήσεις δραστηριοτήτων .......................................................................... 207

Bιβλιογραφία ελληνική / ξενόγλωσση ................................................................................. 234

Γλωσσάρι Όρων ....................................................................................................................................... 239

9¶ E P I E X O M E N A

Page 10: Γλώσσες Προγραμματισμού II
Page 11: Γλώσσες Προγραμματισμού II

B·ÛÈΤ˜ ŒÓÓÔȘ Ù˘ AÓÙÈÎÂÈÌÂÓÔÛÙÚÂÊÔ‡˜ ÚÔÛ¤ÁÁÈÛ˘

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να παρουσιάσει τις σηµαντικότερες έννοιες της

αντικειµενοστρεφούς προσέγγισης µέσα από παραδείγµατα της καθηµερινής

ζωής, δίνοντας έµφαση κυρίως στις έννοιες αυτές καθ’ εαυτές, παρά στον

ακριβή ορισµό τους.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε µελετήσει το κεφάλαιο αυτό θα µπορείτε να:

• περιγράψετε τη διαφορά µεταξύ κλάσης και στιγµιότυπου,

• δώσετε 5 τουλάχιστον παραδείγµατα κλάσεων,

• αναφέρετε αντικείµενα του πραγµατικού κόσµου που περιγράφονται από

τις παραπάνω κλάσεις,

• εντοπίζετε σχέσεις γενίκευσης–εξειδίκευσης µεταξύ κλάσεων,

• εντοπίζετε σχέσεις συνάθροισης µεταξύ κλάσεων,

• δώσετε από 3 τουλάχιστο σχέσεις γενίκευσης–εξειδίκευσης και συνάθροισης,

• περιγράψετε 2 τουλάχιστο συστήµατα του πραγµατικού κόσµου σαν συνά-

θροιση συνεργαζόµενων αντικειµένων,

• εξηγήσετε γιατί είναι σηµαντική η έννοια της απόκρυψης πληροφορίας,

• αναφέρετε 5 τοµείς στους οποίους η αντικειµενοστρεφής προσέγγιση βελ-

τιώνει την ποιότητα του λογισµικού,

• περιγράψετε τί είναι ένα αντικειµενοστρεφές περιβάλλον ανάπτυξης,

• δώσετε ένα ορισµό για τον όρο αντικείµενο.

ŒÓÓÔȘ ÎÏÂȉȿ

1∫ ∂ º ∞ § ∞ π √

• αντικείµενο (object)

• κλάση (class)

• στιγµιότυπο (instance)

• σχέση κλάσεων

• γενίκευση/ εξειδίκευση

• συνάθροιση (aggregation)

• απόκρυψη πληροφορίας

(information hiding)

Page 12: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 1 : B ∞ ™ π ∫ ∂ ™ ∂ ¡ ¡ √ π ∂ ™ ∆ ∏ ™ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ ¶ ƒ √ ™ ∂ ° ° π ™ ∏ ™1 2

• πέρασµα µηνύµατος

(message passing)

• δηµιουργία – καταστροφή αντι-

κειµένου

• υλοποίηση αντικειµένου

(object implementation)

• διεπαφή αντικειµένου

(object interface)

• διάγραµµα κλάσεων

(class diagram)

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Η παραδοσιακή προσέγγιση στην ανάπτυξη συστηµάτων, την οποία ήδη γνω-

ρίσατε στη Θεµατική Ενότητα «Εισαγωγή στην Πληροφορική», θεωρεί τη

διεργασία σαν βασικό δοµικό στοιχείο του συστήµατος, το οποίο αποτελείται

από διεργασίες και από δεδοµένα πάνω στα οποία αυτές επιδρούν. Η προ-

σέγγιση αυτή αποδεικνύεται ανεπαρκής για την ανάπτυξη των σύγχρονων

πολύπλοκων σηµερινών συστηµάτων του καθιερωµένου πια γραφικού περι-

βάλλοντος των υπολογιστών. Για την αντιµετώπιση της πολυπλοκότητας

(complexity) των συστηµάτων που αναπτύσσουµε, πολλά έχουµε να διδα-

χθούµε από τον τρόπο µε τον οποίο είναι οργανωµένο το σύµπαν αλλά και ο

φυσικός κόσµος που µας περιβάλει. Ένα αστέρι που πέφτει, ένα παιδί που

µαθαίνει να γράφει, ένα αεροπλάνο που απογειώνεται, αποτελούν µερικά

απλά παραδείγµατα αντικειµένων που απαρτίζουν τον φυσικό κόσµο. Αντι-

κείµενα που αλληλεπιδρούν µεταξύ τους αλλά και που µπορούν να θεωρη-

θούν αποτελούµενα από άλλα επί µέρους αλληλεπιδρόντα αντικείµενα. Ο

άνθρωπος, εξοικειωµένος µε την θεώρηση αυτή, µπορεί εύκολα να αντιµε-

τωπίσει µε τον ίδιο τρόπο και τα συστήµατα λογισµικού που αναπτύσσει. Η

προσέγγιση που βασίζεται στην θεώρηση αυτή είναι γνωστή µε το όνοµα Αντι-

κειµενοστρεφής Προσέγγιση (ΑΠ) και υπόσχεται να δώσει λύση στα πολλά

προβλήµατα της διαδικασίας ανάπτυξης συστηµάτων λογισµικού.

Τα µοντέλα ανάλυσης και σχεδιασµού που αναπτύσσονται σύµφωνα µε την

ΑΠ είναι εύκολα στη κατανόηση καθώς σχετίζονται άµεσα µε την πραγµατι-

κότητα. Η ΑΠ έχει καταφέρει να µειώσει το σηµασιολογικό κενό (semantic

gap) µεταξύ ιδεατού µοντέλου και µοντέλου ανάλυσης του συστήµατος, αλλά

και µεταξύ µοντέλου ανάλυσης και σχεδιασµού, διευκολύνοντας την αντι-

στοίχηση των εννοιών από το ένα µοντέλο στο επόµενο (forward traceability)

ή στο προηγούµενο (backward traceability) [Jacobson 92].

Page 13: Γλώσσες Προγραμματισμού II

Το κεφάλαιο αυτό παρουσιάζει παραδείγµατα από την καθηµερινή ζωή για

να εισάγει τις βασικές έννοιες και να αποδείξει πως η ΑΠ δεν είναι τίποτε

παραπάνω από µεταφορά των εννοιών αυτών στη διαδικασία ανάπτυξης

συστήµατος.

Για σας που θέλετε µια σε βάθος ανάλυση του θέµατος της πολυπλοκότητας

των συστηµάτων λογισµικού αλλά και του τρόπου που αυτή µπορεί να αντι-

µετωπισθεί σύµφωνα µε την ΑΠ µπορείτε να ανατρέξετε στο πρώτο κεφάλαιο

του [Booch 94] µε τίτλο «Complexity» όπου θα βρείτε µια πολύ καλή αλλά

δύσκολη προσέγγιση του θέµατος.

1.1 AÓÙÈΛÌÂÓÔ – KÏ¿ÛË – ™ÙÈÁÌÈfiÙ˘Ô

Τι είναι αντικείµενο;

Αν παρατηρήσουµε το περιβάλλον γύρω µας, θα διακρίνουµε ένα σύνολο

από οντότητες µε τις οποίες αλληλεπιδρούµε συνεχώς. Οι οντότητες αυτές

που είναι είτε απλές όπως ο πιστός µας σκύλος, είτε πιο σύνθετες, όπως η

δανειστική βιβλιοθήκη, η τράπεζα και η υπηρεσία ύδρευσης, µας παρέχουν

ένα σύνολο από εξυπηρετήσεις αλλά και χρησιµοποιούν εξυπηρετήσεις που

εµείς προσφέρουµε. Η οντότητα «Tράπεζα» παρέχει την πολύ γνωστή σε

όλους σας εξυπηρέτηση της πιστωτικής κάρτας, ο ΟΤΕ παρέχει την εξυπη-

ρέτηση παροχής τηλεφωνικής γραµµής, την εξυπηρέτηση του 131, ενώ εσείς

προσφέρετε την εξυπηρέτηση παροχής τροφής στο σκύλο σας. Γενικά µπο-

ρούµε να πούµε, ότι ο κόσµος αποτελείται από αντικείµενα απλά ή σύνθετα,

τα οποία αλληλεπιδρούν µεταξύ τους.

Τι είναι κλάση και τι στιγµιότυπο;

Ας δούµε όµως τη διαφορά που υπάρχει µεταξύ του Αζώρ[1] και του όρου

«πιστός σκύλος». Ο όρος «πιστός σκύλος» αναφέρεται στην αφηρηµένη

έννοια που περιγράφει τα κοινά χαρακτηριστικά ενός συνόλου πραγµατικών

αντικειµένων του φυσικού κόσµου. Αντίθετα, ο Αζώρ είναι ένα από τα πραγ-

µατικά αντικείµενα που η αφηρηµένη έννοια «πιστός σκύλος» περιγράφει.

Όλοι σας γνωρίζετε τα χαρακτηριστικά που προσδιορίζει η αφηρηµένη

έννοια «Τράπεζα» και αυτό σας διευκολύνει ώστε να ζητήσετε την έκδοση

βιβλιαρίου καταθέσεων µε την πρώτη σας επίσκεψη στην τράπεζα που πρό-

σφατα άνοιξε στην γειτονιά σας.

1 3A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ – K § ∞ ™ ∏ – ™ ∆ π ° ª π √ ∆ À ¶ √

[1] Tου πιστού µου σκύλου

Page 14: Γλώσσες Προγραμματισμού II

1 4 ∫ ∂ º ∞ § ∞ π √ 1 : B ∞ ™ π ∫ ∂ ™ ∂ ¡ ¡ √ π ∂ ™ ∆ ∏ ™ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ ¶ ƒ √ ™ ∂ ° ° π ™ ∏ ™

Για κάθε αντικείµενο του φυσικού κόσµου υπάρχει ή µπορούµε να ορίσου-

µε, µια αφηρηµένη έννοια που περιγράφει, αφενός τον τρόπο µε τον οποίο

το αντικείµενο επικοινωνεί µε το περιβάλλον του, αφετέρου το πώς αυτό

είναι οργανωµένο εσωτερικά. Η ΑΠ ονοµάζει στιγµιότυπα (instances) τα

πραγµατικά αντικείµενα και κλάσεις (classes) τις αφηρηµένες έννοιες που τα

περιγράφουν.

O Αζώρ είναι ένα στιγµιότυπο της κλάσης «πιστός σκύλος», όπως το υποκα-

τάστηµα 223 της Αγροτικής Τράπεζας της γειτονιάς σας είναι στιγµιότυπο της

κλάσης «Αγροτική Τράπεζα». Λάθος! θα µου πείτε. Ναι µεν, ο Αζώρ είναι

στιγµιότυπο της κλάσης «πιστός σκύλος», η Τράπεζα της γειτονιάς µας όµως

είναι στιγµιότυπο της κλάσης «Τράπεζα», όπως διαφαίνεται από το προηγού-

µενο κείµενο. Μήπως όµως και ο Αζώρ είναι στιγµιότυπο της κλάσης «σκύ-

λος» και όχι της «πιστός σκύλος»; και γιατί όχι της κλάσης «θηλαστικό»; Όπως

βλέπουµε, υπάρχουν δύο τουλάχιστον σε κάθε περίπτωση αφηρηµένες έννοι-

ες που διεκδικούν τα εν λόγω στιγµιότυπα. Και δεν είναι βέβαια λάθος να

πούµε ότι ο Αζώρ είναι στιγµιότυπο της κλάσης «θηλαστικό», ούτε πως ο

Αζώρ είναι στιγµιότυπο της κλάσης «σκύλος» αλλά και της «πιστός σκύλος».

Σχέσεις µεταξύ των κλάσεων

Είναι φανερό ότι υπάρχει σχέση (association) µεταξύ των τριών παραπάνω

κλάσεων. Η κλάση «πιστός σκύλος» είναι εξειδίκευση της κλάσης «σκύλος»,

της οποίας αποτελεί γενίκευση η κλάση «θηλαστικό». Η ΑΠ ονοµάζει αυτή

τη µορφή σχέσης που υπάρχει µεταξύ των αφηρηµένων εννοιών (κλάσεων),

σχέση γενίκευσης – εξειδίκευσης.

Ας θεωρήσουµε πάλι το παράδειγµα της τράπεζας. Η αφηρηµένη έννοια

«Τράπεζα» ορίζει πως κάθε στιγµιότυπό της, αποτελεί συνάθροιση ενός

κτίσµατος, ενός αριθµού τερµατικών, ενός διευθυντή, ενός αριθµού υπαλ-

λήλων, κ.ο.κ. Οι όροι κτίσµα, τερµατικό, διευθυντής και υπάλληλος προσ-

διορίζουν µε τη σειρά τους, τις αφηρηµένες έννοιες των επί µέρους αντι-

κειµένων από τα οποία αποτελείται η τράπεζα της γειτονιάς σας. Η σχέση

που συνδέει την κλάση «Τράπεζα» µε την κλάση «Τερµατικό», όπως και

µε την κλάση «Υπάλληλος», είναι σύµφωνα µε την ΑΠ µια σχέση

«όλου–µέρους» (whole–part) ή αλλιώς σχέση συνάθροισης (aggregation).

Και η µεν «Τράπεζα» είναι το σύνθετο (aggregate) αντικείµενο, το όλο, τα

δε «κτίσµα», «τερµατικό», κ.ο.κ. αποτελούν τα συνθετικά του, τα µέρη από

τα οποία αποτελείται.

Page 15: Γλώσσες Προγραμματισμού II

∆ιαβάστε τώρα προσεκτικά την παρακάτω περιγραφή.

1 5A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ – K § ∞ ™ ∏ – ™ ∆ π ° ª π √ ∆ À ¶ √

¶·Ú¿‰ÂÈÁÌ· 1

«fast food ο Γιώργος»

Ο Γιώργος αποφασίζει να ανοίξει ένα µαγαζί πρόχειρου φαγητού (fast food).

Γνωρίζει πως χρειάζεται ένα φούρνο µικροκυµάτων, µια τοστιέρα, ένα

ψυγείο, ένα πλυντήριο πιάτων, και ορισµένα άλλα αντικείµενα, τα οποία

είναι απαραίτητα για να παρέχει σωστές υπηρεσίες το µαγαζί του. Ο Γιώρ-

γος αρχίζει µε την ετοιµασία του χώρου και όταν αυτός είναι έτοιµος, ειδο-

ποιεί να του φέρουν και εγκαταστήσουν τα επί µέρους αντικείµενα–

συσκευές που απαρτίζουν το fast food. Μια ανακοίνωση στην είσοδο κάτω

από την πινακίδα «fast food ο Γιώργος» γράφει «Ζητούνται υπάλληλοι».

Μετά από µερικές µέρες το µαγαζί είναι έτοιµο, και ο Γιώργος µε τους δύο

υπαλλήλους που ήδη προσέλαβε, τη Μαίρη και το Νίκο, είναι έτοιµοι να

υποδεχτούν τον πρώτο τους πελάτη.

Ο Χρήστος, το όνοµα του πρώτου πελάτη, µπαίνει στο µαγαζί. «Ένα τοστ

µε τυρί ζαµπόν παρακαλώ, µια τυρόπιτα και µια παγωµένη ΗΒΗ». Ο Γιώρ-

γος λέει στη Μαίρη «Φτιάξε σε παρακαλώ το τοστ», και αυτός αναλαµβά-

νει την τυρόπιτα. ∆ιαπιστώνει όµως πως είναι κρύα και αποφασίζει να χρη-

σιµοποιήσει το φούρνο µικροκυµάτων. Εκείνη τη στιγµή στο µαγαζί µπαί-

νει ένας άλλος πελάτης, ο Κώστας, και δίνει και αυτός την παραγγελία του.

Μετά από λίγο ο Χρήστος πήρε µια σακούλα και αφού πλήρωσε βγήκε από

το µαγαζί.

Αφού διαβάσατε προσεκτικά το κείµενο του Παραδείγµατος 1/κεφ.1, προ-

σπαθήστε να αναγνωρίσετε και καταγράψετε κλάσεις (αφηρηµένες έννοι-

ες) και τα αντίστοιχα στιγµιότυπά τους. Στη συνέχεια, διαβάστε προσεκτι-

κά πάλι τα περί κλάσεων και αντικειµένων στην ενότητα 1.1 και κάντε τις

απαραίτητες διορθώσεις και προσθήκες. Αφού ολοκληρώσετε, ανατρέξτε

στο τέλος του βιβλίου για να επιβεβαιώσετε τα αποτελέσµατα σας.

¢Ú·ÛÙËÚÈfiÙËÙ· 1.1

Page 16: Γλώσσες Προγραμματισμού II

1 6 ∫ ∂ º ∞ § ∞ π √ 1 : B ∞ ™ π ∫ ∂ ™ ∂ ¡ ¡ √ π ∂ ™ ∆ ∏ ™ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ ¶ ƒ √ ™ ∂ ° ° π ™ ∏ ™

Κάθε κλάση έχει έναν αναγνωριστή

Ο λογαριασµός που µόλις ανοίξατε στην τράπεζα έχει αριθµό 123–45678–09.

Ο αριθµός αυτός µοναδιαία διακρίνει το στιγµιότυπο της κλάσης «λογαρια-

σµός» από τα υπόλοιπα στιγµιότυπα της ίδιας κλάσης και καλείται αναγνω-

ριστής (identifier). Κάθε κλάση, είτε έχει από τη φύση της έναν αναγνωρι-

στή, είτε θα πρέπει να της καθορίσουµε εµείς έναν.

1.2 ∆o Û‡ÛÙËÌ· ÛÙËÓ A¶

Το σύστηµα σαν συνάθροιση αντικειµένων

Στη συνέχεια θα χρησιµοποιήσουµε τον όρο σύστηµα αντί του όρου οντό-

τητα και θα αναφερθούµε στην οργάνωση και λειτουργία του συστήµατος

«fast food ο Γιώργος», το οποίο αποτελεί χαρακτηριστικό παράδειγµα του

τρόπου µε τον οποίο συστήµατα του πραγµατικού κόσµου είναι οργανωµέ-

να και λειτουργούν. Η αφηρηµένη έννοια fast food περιγράφει αντικείµενα

που αποτελούνται από ένα κτίσµα, έναν ιδιοκτήτη, υπαλλήλους, ψυγείο,

φούρνο µικροκυµάτων, τοστιέρα, κ.λ.π. Λέµε ότι η κλάση fast food είναι η

συνάθροιση των κλάσεων κτίσµα, ιδιοκτήτης, υπάλληλος ή ότι οι κλάσεις

αυτές αποτελούν τα συνθετικά της κλάσης fast food. Μόλις αναγνωρίσαµε

και καταγράψαµε µια σχέση συνάθροισης µεταξύ των κλάσεων του συστή-

µατός µας. Η ΑΠ θεωρεί το κάθε σύστηµα ως συνάθροιση των επί µέρους

αντικειµένων από τα οποία αποτελείται.

Θεωρήστε το κείµενο του Παραδείγµατος 1 και προσπαθήστε να αναγνω-

ρίσετε και να καταγράψετε κλάσεις που σχετίζονται µε σχέση γενίκευ-

σης–εξειδίκευσης, καθώς και κλάσεις που σχετίζονται µε σχέση συνάθροι-

σης. Στη συνέχεια διαβάστε προσεκτικά πάλι τα περί σχέσεων κλάσεων και

κάντε τις απαραίτητες διορθώσεις και προσθήκες. Αφού ολοκληρώσετε ανα-

τρέξτε στο τέλος του βιβλίου για να δείτε µια δική µας καταγραφή.

¢Ú·ÛÙËÚÈfiÙËÙ· 1.2

Τα αντικείµενα επικοινωνούν µεταξύ τους µε µηνύµατα

«Objects do things, and we ask them to perform what they do by sending them

messages» [Booch 94].[2]

[2] «Τα αντικείµενα εκτελούν ενέργειες και εµείς τους ζητούµε να τις εκτελέσουν

αποστέλλοντας τους µηνύµατα».

Page 17: Γλώσσες Προγραμματισμού II

Το σύστηµα µας παρέχει, αλλά και χρησιµοποιεί εξυπηρετήσεις άλλων αντι-

κειµένων (συστηµάτων) του περιβάλλοντος στο οποίο βρίσκεται. Παρέχει

την εξυπηρέτηση «ζεστή τυρόπιτα» στον πελάτη και χρησιµοποιεί τις εξυ-

πηρετήσεις του ΟΤΕ και των προµηθευτών του.

Ας δούµε τώρα πιο αναλυτικά τον τρόπο µε τον οποίο το σύστηµα µας παρέ-

χει την εξυπηρέτηση «ζεστή τυρόπιτα». Το αντικείµενο που θέλει την εξυ-

πηρέτηση (ο Χρήστος του παραδείγµατος µας) πρέπει να το γνωστοποιήσει

στο σύστηµά µας περνώντας του το µήνυµα «Παρακαλώ µια ζεστή τυρόπι-

τα». Το σύστηµά µας, αναγνωρίζει το µήνυµα, διακρίνει πως είναι µια από

τις υπηρεσίες που παρέχει, και συµπεριφέρεται κατά τέτοιο τρόπο ώστε να

προσφέρει τη ζητούµενη υπηρεσία. ∆εν θα συνέβαινε το ίδιο για το µήνυµα

«Σας παρακαλώ ένα ποδήλατο». Το σύστηµα αναγνωρίζει οτι δεν είναι υπη-

ρεσία που µπορεί να προσφέρει και ενηµερώνει γι’ αυτό τον αιτούντα.

Κάθε αντικείµενο είναι αποδέκτης πολλών µηνυµάτων από το εξωτερικό περι-

βάλλον, αλλά αναγνωρίζει ορισµένα και αποκρίνεται µόνο σε αυτά. Γενικά

µπορούµε να πούµε ότι τα αντικείµενα επικοινωνούν µεταξύ τους περνώντας

το ένα στο άλλο µηνύµατα. Ο τρόπος που τα µηνύµατα αυτά περνούν διαφέ-

ρει από περίπτωση σε περίπτωση (οµιλία, γραφή, νοήµατα, ταχυδροµείο,

e–mail, κλπ.) χωρίς αυτό να επηρεάζει την παρεχόµενη εξυπηρέτηση.

Τα επιµέρους αντικείµενα του συστήµατος συνεργάζονται για την παρο-

χή των εξυπηρετήσεών του

«We view the world as a set of autonomous agents that collaborate to performsome higher level behavior» [Booch 94] [3].

Ο Γιώργος µόλις δέχτηκε το µήνυµα του Χρήστου, του πρώτου πελάτη, χρησι-

µοποίησε τον προφορικό λόγο για να περάσει το µήνυµα «Φτιάξε σε παρακα-

λώ το τοστ» στο αντικείµενο Μαίρη, αλλά πρέπει να ρυθµίσει το πλήκτρο χρό-

νου του φούρνου µικροκυµάτων και στη συνέχεια να πιέσει το πλήκτρο

«START», για να γνωστοποιήσει στο αντικείµενο «φούρνο» ότι θέλει να του

ζεστάνει την τυρόπιτα. Η Μαίρη αντίστοιχα χρησιµοποιεί τις εξυπηρετήσεις

της τοστιέρας για την παρασκευή του τοστ. Το πλυντήριο πιάτων µε τη σειρά

του περνάει το µήνυµα «θέλω νερό» στο αντικείµενο βρύση, µε διαφορετικό

φυσικά τρόπο απ’ ότι περνάει στο αντικείµενο Νίκος το µήνυµα «το πλύσιµο

τελείωσε». Στη δεύτερη αυτή περίπτωση παράγει ένα συγκεκριµένο ήχο για να

γνωστοποιήσει στο Νίκο ότι ολοκλήρωσε την εξυπηρέτηση που του ζητήθηκε.

[3] «Bλέπουµε τον κόσµο αποτελούµενο από αυτόνοµους πράκτορες που συνεργά-

ζονται για να προσφέρουν µια υψηλότερου επιπέδου συµπεριφορά»

1 7∆ O ™ À ™ ∆ ∏ ª ∞ ™ ∆ ∏ ¡ A ¶

Page 18: Γλώσσες Προγραμματισμού II

1 8 ∫ ∂ º ∞ § ∞ π √ 1 : B ∞ ™ π ∫ ∂ ™ ∂ ¡ ¡ √ π ∂ ™ ∆ ∏ ™ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ ¶ ƒ √ ™ ∂ ° ° π ™ ∏ ™

Όπως βλέπουµε, τα αντικείµενα του συστήµατός µας συνεργάζονται αρµονι-

κά µεταξύ τους. Κάθε σύστηµα, σύµφωνα µε την ΑΠ, µπορεί να θεωρηθεί

σαν µια συνάθροιση αντικειµένων, τα οποία συνεργάζονται µεταξύ τους αντα-

λάσσοντας µηνύµατα για να παρέχουν τις υπηρεσίες του συστήµατος.

Τα εξωτερικά αντικείµενα έχουν πρόσβαση µόνο σε ορισµένα αντικείµε-

να του συστήµατός µας

Ο πελάτης του fast food µπορεί να ζητήσει εξυπηρετήσεις από τους σερβιτό-

ρους και τον ιδιοκτήτη, δεν µπορεί όµως να χρησιµοποιήσει την τοστιέρα, τον

φούρνο, την βρύση και τα άλλα αντικείµενα από τα οποία αποτελείται το

σύστηµα µας. Αυτό αποτελεί µεν έναν περιορισµό, ο οποίος όµως, αφενός

διευκολύνει την επικοινωνία του πελάτη µε το fast food, αφετέρου διευκολύ-

νει τον ιδιοκτήτη να τροποποιεί την εσωτερική σύνθεση του συστήµατος του

(νέα µηχανήµατα κλπ.) χωρίς να επηρεάζει τον τρόπο µε τον οποίο οι πελά-

τες επικοινωνούν µε αυτό. Σε διαφορετική περίπτωση και όταν ο ιδιοκτήτης,

για διάφορους λόγους, άλλαζε την τοστιέρα µε µια πιο σύνθετη, θα έπρεπε να

ενηµερώσει όλους τους πελάτες του για τον τρόπο λειτουργίας της.

Όλα γενικά τα αντικείµενα, απλά ή σύνθετα, είναι κατασκευασµένα µε τέτοιο

τρόπο ώστε να εµφανίζουν προς τα έξω µόνο εκείνα τα στοιχεία τους, που

συµµετέχουν στη διαδικασία περάσµατος των µηνυµάτων και για το λόγο

αυτό πρέπει να είναι γνωστά στα άλλα αντικείµενα που χρησιµοποιούν τις

εξυπηρετήσεις τους. Για να χρησιµοποιήσουµε το φούρνο µικροκυµάτων

θέλουµε πρόσβαση µόνο σε ορισµένα πλήκτρα, τα οποία µας βοηθούν να

περάσουµε στο φούρνο τα µηνύµατά µας. Τέτοια είναι τα πλήκτρα «start»,

«stop» και «open door». Τα πλήκτρα αυτά, λέµε ότι, αποτελούν την διεπα-

φή (interface) της κλάσης «φούρνος» µε την κλάση «πρόσωπο». O Γιώργος,

για παράδειγµα, σαν χρήστης του αντικειµένου «φούρνος», δεν είναι ανά-

γκη να γνωρίζει την εσωτερική δοµή του. Λέµε ότι ο φούρνος αποκρύπτει

(hides) το εσωτερικό του, στο οποίο όµως έχει πρόσβαση ο κατασκευαστής

του και βέβαια αυτός που θα χρειαστεί να τον επισκευάσει.

Μόλις καταγράψαµε µια εφαρµογή της βασικής αρχής της απόκρυψης πλη-

ροφορίας (information hiding). Σύµφωνα µε την ΑΠ, «κάθε σύστηµα απο-

κρύπτει αυτά που πρέπει να αποκρύψει και κάνει ορατά µόνο τα απαραίτητα».

Έτσι διακρίνουµε για κάθε αντικείµενο δύο τµήµατα: το ένα αποτελεί την υλο-

ποίηση του αντικειµένου (object implementation) και το άλλο τη διεπαφή του

(object interface) διαµέσου της οποίας επικοινωνεί µε το περιβάλλον του.

Page 19: Γλώσσες Προγραμματισμού II

∞ÓÙÈΛÌÂÓÔ – ∫Ï¿ÛË – ™ÙÈÁÌÈfiÙ˘Ô

Θα παρατηρήσατε ίσως, ότι στο κείµενο χρησιµοποιείται ο όρος αντικεί-

µενο και για την αφηρηµένη έννοια (κλάση) αλλά και για τα στιγµιότυπά

της. Γενικά η ΑΠ θεωρεί όλες τις οντότητες, πραγµατικές και αφηρηµένες,

αντικείµενα (οbjects). Σύµφωνα µε τη θεώρηση αυτή αντικείµενο είναι η

κλάση, το στιγµιότυπο αλλά και η σχέση µεταξύ δύο κλάσεων. Επειδή έχει

σχεδόν επικρατήσει στη βιβλιογραφία ο όρος αντικείµενο αντί του όρου

στιγµιότυπου, θα χρησιµοποιούµε στη συνέχεια και τους δύο όρους, µε τα

συµφραζόµενα να ορίζουν την πραγµατική σηµασία.

1 9¢ ∏ ª π √ À ƒ ° π ∞ – K ∞∆∞ ™ ∆ ƒ √ º ∏ ∞ ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ À

1.3 ¢ËÌÈÔ˘ÚÁ›· – K·Ù·ÛÙÚÔÊ‹ ·ÓÙÈÎÂÈ̤ÓÔ˘

Είναι αυτονόητο να παρατηρήσουµε, ότι η αφηρηµένη έννοια fast food δεν

µπορεί να δεχτεί µηνύµατα και άρα να παρέχει οποιοδήποτε τύπο εξυπηρέ-

τησης. Αντίθετα, ορίζει τα µηνύµατα τα οποία µπορούν να δεχτούν τα στιγ-

µιότυπά της και επιπλέον προσδιορίζει τη συµπεριφορά τους σε αυτά. Εξυ-

πηρετήσεις παρέχουν µόνο τα στιγµιότυπα σε απόκριση των µηνυµάτων που

δέχονται. Αν θέλετε λοιπόν να φάτε ζεστή τυρόπιτα, φροντίστε να βρείτε ένα

στιγµιότυπο τύπου fast food ή να δηµιουργήσετε ένα[4] και να του στείλετε

το κατάλληλο µήνυµα.

Όταν το αντικείµενο δεν χρησιµοποιείται πλέον θα πρέπει να ελευθερώσει τους

πόρους που κατέχει. Έτσι το fast food ο Γιώργος θα πρέπει να ελευθερώσει το

κτίσµα, τους υπαλλήλους, τον αριθµό τηλεφώνου, κ.λπ. ώστε αυτά να χρησι-

µοποιηθούν από άλλο σύστηµα. Το αντικείµενο πρέπει να καταστραφεί.

1.4 AÓÙÈÎÂÈÌÂÓÔÛÙÚÂÊ‹˜ ÚÔÛ¤ÁÁÈÛË ·Ó¿Ù˘Í˘ Û˘ÛÙËÌ¿ÙˆÓÏÔÁÈÛÌÈÎÔ‡

Η ΑΠ δεν είναι τίποτε παραπάνω από εφαρµογή των παραπάνω, κατά κύριο

λόγο, γενικών αρχών στη διαδικασία ανάπτυξης συστηµάτων λογισµικού.

Έτσι, σύµφωνα µε την ΑΠ, ένα αντικείµενο του πραγµατικού κόσµου ανα-

παρίσταται σαν αντικείµενο στις φάσεις της ανάλυσης, του σχεδιασµού αλλά

και της υλοποίησης. Η αντικειµενοστρεφής µορφή προγραµµατισµού θεω-

[4] Στην περίπτωση µας βέβαια δεν θα δηµιουργήσετε στιγµιότυπο, αλλά αυτό θα

κάνετε πολύ συχνά στα προγράµµατα σας, όπου η δηµιουργία αντικειµένων είναι

απλούστερη και δεν κοστίζει τόσο.

Page 20: Γλώσσες Προγραμματισμού II

2 0 ∫ ∂ º ∞ § ∞ π √ 1 : B ∞ ™ π ∫ ∂ ™ ∂ ¡ ¡ √ π ∂ ™ ∆ ∏ ™ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ ¶ ƒ √ ™ ∂ ° ° π ™ ∏ ™

ρεί το πρόγραµµα αποτελούµενο από αντικείµενα τα οποία συνεργάζονται

µεταξύ τους για την παροχή των εξυπηρετήσεών του. Το σύστηµα, µε τη

σειρά του, θεωρείται στο ευρύτερο περιβάλλον ένα αντικείµενο, το οποίο

παρέχει αλλά και χρησιµοποιεί εξυπηρετήσεις.

Ένα αντικειµενοστρεφές περιβάλλον ανάπτυξης, όπως για παράδειγµα αυτό

της Java, είναι ένα περιβάλλον που υποστηρίζει την ανάπτυξη συστηµάτων

της παραπάνω µορφής. ∆ιαθέτει µηχανισµούς απόκρυψης πληροφορίας,

περάσµατος µηνυµάτων, δηµιουργίας και καταστροφής στιγµιοτύπων, ανα-

παράστασης της γενικευµένης ιεραρχίας, αλλά και άλλους που θα δούµε στα

επόµενα κεφάλαια. Οι µηχανισµοί αυτοί βελτιώνουν αναµφισβήτητα την ποι-

ότητα του λογισµικού ως προς τα χαρακτηριστικά του:

• επαναχρησιµοποίηση (reusability)

• επεκτασιµότητα (extendibility)

• ορθότητα (correctness)

• ευρωστία (robustness)

• συντηρησιµότητα (maintainability)

Μια πολύ καλή αναφορά στα γενικότερα πλεονεκτήµατα της τεχνολογίας

αντικειµένων (Object Technology) γίνεται στο κεφάλαιο 3 του βιβλίου

[Martin 92].

∆Ô ·ÓÙÈΛÌÂÓÔ Û‡Ìʈӷ Ì ÙÔÓ Booch.

Παρόλο που το αντικείµενο αποτελεί το βασικό δοµικό στοιχείο της ΑΠ,

δεν υπάρχει ένας κοινά αποδεκτός ορισµός γι’ αυτό. Από το σύνολο των

ορισµών, διακρίνουµε αυτόν του Booch, ενός από τους σηµαντικότερους

ερευνητές στην περιοχή της ΑΠ.

«Ένα αντικείµενο έχει κατάσταση, συµπεριφορά και ταυτότητα. Η κατά-

σταση και η συµπεριφορά οµοειδών αντικειµένων ορίζονται από την κοινή

τους κλάση. Οι όροι στιγµιότυπο και αντικείµενο χρησιµοποιούνται εναλ-

λακτικά» [Booch 94].

∆ιαβάστε το παρακάτω κείµενο, για την καλύτερη κατανόηση των εννοι-

ών κατάσταση, συµπεριφορά και ταυτότητα.

(συνέχεια…)

Page 21: Γλώσσες Προγραμματισμού II

2 1A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º ∏ ™ ¶ ƒ √ ™ ∂ ° ° π ™ ∏ ∞ ¡ ∞ ¶ ∆ À • ∏ ™ ™ À ™ ∆ ∏ ª ∞∆ ø ¡ § √ ° π ™ ª π ∫ √ À

(…συνέχεια)

Στα τρία τηλέφωνα που έχετε στο σπίτι σας έχετε φροντίσει να δώσετε ένα

διαφορετικό όνοµα στο καθένα ώστε να µπορείτε να αναφέρεστε σε αυτό.

Έχετε δηµιουργήσει ένα αναγνωριστή ή µία ταυτότητα όπως πιο απλά θα

λέγαµε. Το τηλέφωνο δέχεται από σας το µήνυµα που του περνάτε πιέζο-

ντας το πλήκτρο 0, αλλά η συµπεριφορά του, δηλαδή η αντίδραση του στο

µήνυµα αυτό εξαρτάται από την κατάσταση στην οποία το αντικείµενο βρί-

σκεται. Έτσι, διαφορετική είναι η συµπεριφορά του αν είναι σε κατάστα-

ση συνδιάλεξης, αναµονής, απάντησης, ή µε το ακουστικό κατεβασµένο.

Η συµπεριφορά ενός αντικειµένου άµεσα εξαρτάται από την κατάσταση

στην οποία το αντικείµενο βρίσκεται.

Αναφερόµενοι στο κείµενο του Παραδείγµατος 1, αναγνωρίστε και κατα-

γράψτε τις σχέσεις των κλάσεων της αριστερής στήλης µε αυτές της δεξιάς

του παρακάτω πίνακα. Χρησιµοποιήστε την UML σηµειολογία που ανα-

φέραµε στη ∆ραστηριότητα 1.2.

Κλάση Κλάση

Ιδιοκτήτης fast food

Σερβιτόρος Ηλεκτρική συσκευή

Πελάτης Πρόσωπο

Τοστιέρα

Φούρνος µικροκυµάτων

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘1.1

Για την γνωστή σας συσκευή του αυτόµατου τηλεφωνητή, δώστε ένα του-

λάχιστο µήνυµα, για το οποίο η συσκευή έχει συµπεριφορά εξαρτώµενη

από την κατάστασή της. Περιγράψτε τις διαφορετικές καταστάσεις, αλλά

και τις αντίστοιχες συµπεριφορές της.

¢Ú·ÛÙËÚÈfiÙËÙ· 1.3

Page 22: Γλώσσες Προγραμματισμού II

2 2 ∫ ∂ º ∞ § ∞ π √ 1 : B ∞ ™ π ∫ ∂ ™ ∂ ¡ ¡ √ π ∂ ™ ∆ ∏ ™ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ ¶ ƒ √ ™ ∂ ° ° π ™ ∏ ™

™‡ÓÔ„Ë

Στο κεφάλαιο αυτό, παραθέσαµε ορισµένες από τις βασικές έννοιες πάνω στις

οποίες βασίζεται η αντικειµενοστρεφής ανάπτυξη συστηµάτων. Χρησιµοποι-

ήθηκαν παραδείγµατα από την καθηµερινή ζωή για να δοθεί έµφαση στην

απλότητα των εννοιών και στο γεγονός ότι ο άνθρωπος είναι ήδη εξοικειω-

µένος µε τις έννοιες αυτές. Οι έννοιες της κλάσης, του αντικειµένου, της από-

κρυψης πληροφορίας, της επικοινωνίας µε πέρασµα µηνυµάτων, της γενί-

κευσης–εξειδίκευσης κ.ο.κ. απέδειξαν, ότι είναι ικανές να ανταποκριθούν σε

µεγάλο βαθµό στις αυξηµένες απαιτήσεις της διαδικασίας ανάπτυξης των

πολύπλοκων σηµερινών συστηµάτων λογισµικού.

Συµπερασµατικά, το αντικείµενο έρχεται να αντικαταστήσει τη διεργασία και

να µας οδηγήσει από την διαδικαστική (procedural) στην αντικειµενοστρε-

φή µορφή προγραµµατισµού. Μια µορφή, που υπόσχεται να λύσει πολλά από

τα προβλήµατα της διαδικασίας ανάπτυξης συστηµάτων λογισµικού.

BÈ‚ÏÈÔÁÚ·Ê›·[1] [Booch 94]

Grady Booch, «Object–Oriented Analysis and Design with applications»

second edition, Benjamin/Cummings Publishing Company Inc, 1994.

Αποτελεί ένα από τα καλύτερα βιβλία στο χώρο της αντικειµενοστρε-

φούς προσέγγισης. Η σηµαντική του συµβολή είναι κυρίως στη φάση

του σχεδιασµού για την οποία κατά την γνώµη µου αποτελεί και το

καλύτερο από τα διαθέσιµα βιβλία. Ο Booch εξ άλλου, µε τον Jacobson

και τον Rumbaugh είναι οι δηµιουργοί της Unified Modeling Language

(UML), της πρώτης γλώσσας που έγινε πρότυπο για αντικειµενοστρε-

φή ανάπτυξη συστηµάτων.

[2] [Jacobson 92]

Ivar Jacobson, «Object–Oriented Software Engineering – A use case

Driven Approach», Addison–Wesley, 1992.

Αποτελεί ένα από τα καλύτερα βιβλία στο χώρο της αντικειµενοστρε-

φούς προσέγγισης. Έγινε περισσότερο γνωστό από την έννοια του «use

case» (περίπτωσης χρήσης) που εισήγαγε στην διαδικασία ανάλυσης του

συστήµατος και η οποία υιοθετήθηκε από το σύνολο σχεδόν των µεθο-

δολογιών αντικειµενοστρεφούς ανάπτυξης συστηµάτων λογισµικού.

Αναφέρεται κυρίως στις φάσεις της ανάλυσης και σχεδιασµού οι οποί-

Page 23: Γλώσσες Προγραμματισμού II

ες αποτελούν αντικείµενο άλλης θεµατικής ενότητας. Ανήκει στα βιβλία

που δεν θα πρέπει να λείπουν από την βιβλιοθήκη του επαγγελµατία στο

χώρο της ανάπτυξης συστηµάτων.

[3] [Martin 92]

J. Martin, J. Odell, «Object Oriented Analysis & Design», Prentice

Hall, 1992.

Το βιβλίο αυτό δίνει απόψεις, οι οποίες σε πολλές περιπτώσεις είναι δια-

φορετικές από τις ευρέως θεωρούµενες στον χώρο της αντικειµενοστρε-

φούς προσέγγισης. Στις απόψεις αυτές αποφύγετε να ανατρέξετε στο

παρόν στάδιο, γιατί µπορεί να σας δηµιουργήσουν σύγχυση. Αντίθετα,

οι απόψεις αυτές µπορούν να αποτελέσουν πηγή προβληµατισµού στο

στάδιο που θα έχετε κατανοήσει και χρησιµοποιήσει αρκετά την ΑΠ.

Η παρατήρηση αυτή δεν ισχύει για το κεφάλαιο 3, στο οποίο γίνεται η

παραποµπή.

[4] [UML 97]

«Unified Modeling Language: UML semantics» version 1.1, Rational

Software, September 97.

2 3B I B § I O ° PA º I A

Page 24: Γλώσσες Προγραμματισμού II
Page 25: Γλώσσες Προγραμματισμού II

EÈÛ·ÁˆÁ‹ ÛÙË Java

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να παρουσιάσει τη διαδικασία ανάπτυξης Java

προγράµµατος καθώς και τον τρόπο που ένα πρόγραµµα Java µπορεί να απο-

τελέσει µέρος µιας ιστοσελίδας του διαδικτύου. Το κεφάλαιο ξεκινά µε µια

πολύ σύντοµη αναφορά στην ιστορία της Java και τους λόγους για τους οποί-

ους η γλώσσα επιλέχτηκε για την παρουσίαση του αντικειµενοστρεφούς προ-

γραµµατισµού.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• αναπτύξετε ένα πρόγραµµα Java, για το οποίο θα σας έχει δοθεί ο πηγαί-

ος κώδικας,

• αναπτύξετε και ενσωµατώσετε σε µία ιστοσελίδα ένα Java πρόγραµµα για

το οποίο σας δίνεται ο πηγαίος κώδικας,

• κάνετε απλές τροποποιήσεις σε δεδοµένο πρόγραµµα Java.

ŒÓÓÔȘ ÎÏÂȉȿ

2∫ ∂ º ∞ § ∞ π √

• συντακτικό γλώσσας

• BNF

• ASCII κώδικας

• Unicode

• δεσµευµένη λέξη

(reserved word)

• λέξη–κλειδί (keyword)

• ευανάγνωστο πρόγραµµα

• συντακτικό λάθος (syntax error)

• σηµασιολογικό λάθος

(semantic error)

• case sensitive

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Οι βασικές έννοιες του Αντικειµενοστρεφούς Προγραµµατισµού (ΑΠ) εισή-

χθησαν από την Simula, αλλά έγιναν γνωστές από την Smalltalk, τη γλώσσα

που θεωρείται πρόγονος του ΑΠ. Οι σχεδιαστές της Smalltalk επηρεάστηκαν

σε µεγάλο βαθµό από την Simula, όπως ακριβώς και ο Bjarne Stroustrup, ο

οποίος πρόσθεσε κλάσεις στην C για να δηµιουργήσει στη συνέχεια τη C++,

στην οποία οφείλεται η ευρεία εξάπλωση του ΑΠ.

Page 26: Γλώσσες Προγραμματισμού II

2 6 ∫ ∂ º ∞ § ∞ π √ 2 : E π ™ ∞ ° ø ° ∏ ™ ∆ ∏ J AVA

Το κεφάλαιο αυτό διακρίνεται σε δύο ενότητες. Στην πρώτη γίνεται µια πολύ

σύντοµη αναφορά στην ιστορία της Java και δίνονται οι λόγοι για τους οποί-

ους η γλώσσα επιλέχτηκε να χρησιµοποιηθεί για την παρουσίαση της αντι-

κειµενοστρεφούς µορφής προγραµµατισµού. Στη δεύτερη ενότητα, παρου-

σιάζεται η διαδικασία ανάπτυξης Java προγράµµατος, αλλά και Java applet,

καθώς και η διαδικασία ενσωµάτωσης Java applet σε ιστοσελίδα.

2.1 IÛÙÔÚ›· Ù˘ Java

Η Java παρουσιάστηκε σαν µια γλώσσα που είχε αφαιρέσει τα «βρώµικα»

στοιχεία της C++ και είχε εισάγει ένα σύνολο από καλά στοιχεία άλλων

γλωσσών όπως η Smalltalk. H ιστορία της γλώσσας ξεκίνησε, όταν µια

οµάδα ερευνητών στην προσπάθεια της να αναπτύξει ενσωµατωµένο λογι-

σµικό (embedded software) για έξυπνες καταναλωτικές συσκευές στα πλαί-

σια του project Green, αποφάσισε να αναπτύξει µια νέα γλώσσα µετά τη δια-

πίστωση ότι η C και η C++ δεν ανταποκρίνονταν στις απαιτήσεις της. Έτσι,

τον Αύγουστο του 1991 εµφανίστηκε µια νέα αντικειµενοστρεφής γλώσσα

µε το όνοµα Oak που είναι το ακρωνύµιο του Object Application Kernel. Η

γλώσσα απλά προστέθηκε στον κατάλογο των καλών γλωσσών προγραµ-

µατισµού µε ουσιαστική υποστήριξη σε εφαρµογές τύπου πελάτη–εξυπηρέ-

τη (client–server) και τίποτε παραπάνω.

Tον Απρίλιο του 1993 έκανε την εµφάνιση του το NCSA MOSAIC 1.0, σαν

πρώτο γραφικό πρόγραµµα πλοήγησης στο διαδίκτυο (Web browser) και η

γλώσσα άρχισε να κάνει τα πρώτα της βήµατα στο χώρο του διαδικτύου, µε

πολύ θετικά αποτελέσµατα. Το στοιχείο αυτό ώθησε την Sun, µετά από µία

αποτυχηµένη προσπάθειά της να πουλήσει τη γλώσσα (Αύγουστος 93), να

χρηµατοδοτήσει την ανάπτυξή της για το 1994, αν και το προηγούµενο έτος

είχε διακόψει σαν µη επιτυχηµένο το αντίστοιχο project. Στα µέσα του 1994

αναπτύχθηκε το πρώτο πειραµατικό πρόγραµµα πλοήγησης µε Java κάτω

από το όνοµα WebRunner[1]. Το φθινόπωρο του ίδιου έτους ο Van Hoff υλο-

ποιεί µε Java τον πρώτο Java διερµηνευτή[2].

Μόλις τον Ιανουάριο του 1995, η γλώσσα πήρε την σηµερινή της ονοµασία

και εµφανίστηκε η πρώτη επίσηµη τεκµηρίωσή της µε την µορφή ενός «white

paper» [Sun 95]. Το Μάιο του ιδίου έτους, η Sun παρουσίασε επίσηµα την Java

[1] Aποτελεί την πρώτη έκδοση του προγράµµατος πλοήγησης HotJava της Sun.

[2] O προηγούµενος Java interpreter είχε αναπτυχθεί από τον Gosling σε C.

Page 27: Γλώσσες Προγραμματισμού II

και το HotJava. Ταυτόχρονα, η Netscape αγόρασε άδεια χρήσης της Java και

ενσωµάτωσε τη γλώσσα στη δεύτερη έκδοση του Netscape, του γνωστού προ-

γράµµατος πλοήγησης. Στη συνέχεια ο ένας µετά τον άλλο οι µεγάλοι κατα-

σκευαστές λογισµικού ανακοίνωναν την απόφαση τους να χρησιµοποιήσουν

την Java, µε αποκορύφωµα την απόφαση της Microsoft τον ∆εκέµβρη του

1995. Η Java καθιερώθηκε πια σαν η γλώσσα που θα πρωτοστατήσει στην

ερχόµενη δεκαετία. Μια αναλυτική αναφορά στο χρονικό της εξέλιξης της

γλώσσας µπορείτε να βρείτε στο διαδίκτυο στη διεύθυνση

http://ils.unc.edu/blaze/java/javahist.html. Μπορείτε επίσης να ανατρέξετε στην

εισαγωγή της Υποενότητας 4, «Γλώσσες προγραµµατισµού», της 3ης Θεµα-

τικής Ενότητας για να δείτε ένα µέρος του γενεαλογικού δένδρου των γλωσ-

σών προγραµµατισµού. Θα διακρίνετε σε αυτό την εξέλιξη της C, αλλά και

της Java, καθώς και τις γλώσσες από τις οποίες, κυρίως αυτές επηρεάστηκαν.

Γιατί Java;

Ορισµένοι από τους λόγους για τους οποίους επιλέξαµε τη Java για την εισα-

γωγή των εννοιών της αντικειµενοστρεφούς προσέγγισης είναι:

• η φορητότητά της, η οποία διασφαλίζει την δυνατότητα εκτέλεσης των

Java προγραµµάτων ανεξάρτητα πλατφόρµας υλικού και λογισµικού,

• η πολύ µεγάλη βιβλιοθήκη έτοιµων κλάσεων που διαθέτει, γεγονός που

διευκολύνει σε µεγάλο βαθµό τη γρήγορη ανάπτυξη εφαρµογών,

• η ραγδαία εξάπλωση που γνωρίζει όσον αφορά τη χρήση της σε ερευνη-

τικά και αναπτυξιακά προγράµµατα,

• η δυνατότητα της να χρησιµοποιηθεί για προγραµµατισµό στο διαδίκτυο,

• το γεγονός ότι είναι, όσον αφορά την υποστήριξη της ΑΠ, πολύ πιο

καθαρή από την C++, η οποία θα µπορούσε να θεωρηθεί σαν λογική

συνέχεια της C,

• η υιοθέτηση µεγάλου µέρους της C.

Ο τελευταίος αυτός λόγος, θα σας δώσει τη δυνατότητα να µπορέσετε πολύ

σύντοµα να τροποποιήσετε ή ακόµη και να δηµιουργήσετε τα δικά σας προ-

γράµµατα Java εκµεταλλευόµενοι την γνώση και εµπειρία σας στη C.

Ενδιαφέρον παρουσιάζουν οι συγκριτικές παρουσιάσεις της γλώσσας µε

άλλες επιτυχηµένες γλώσσες προγραµµατισµού. Μια τέτοια συγκριτική

παρουσίαση µε τις γλώσσες Smalltlk, TCL, Perl, Shells, C και C++ δίνεται

2 7I ™ ∆ √ ƒ π ∞ ∆ ∏ ™ J AVA

Page 28: Γλώσσες Προγραμματισμού II

2 8 ∫ ∂ º ∞ § ∞ π √ 2 : E π ™ ∞ ° ø ° ∏ ™ ∆ ∏ J AVA

στο [Sun 95][3]. Μια πιο αντικειµενική αξιολόγηση µε αντίστοιχη βαθµολό-

γηση των σηµαντικότερων αντικειµενοστρεφών γλωσσών προγραµµατισµού

δίνεται από το άρθρο [Sutherland 95].

2.2 ¢È·‰Èηۛ· ·Ó¿Ù˘Í˘ ÚÔÁÚ¿ÌÌ·ÙÔ˜ Java

∂ÈÛ·ÁˆÁÈΤ˜ ·Ú·ÙËÚ‹ÛÂȘ

Για να µπορέσετε να µελετήσετε την ενότητα αυτή θα πρέπει πρώτα να εξα-

σφαλίσετε πρόσβαση σε ένα περιβάλλον ανάπτυξης Java. Το περιβάλλον αυτό

είναι απαραίτητο για την ανάπτυξη κάθε προγράµµατος Java. Ένα τέτοιο

περιβάλλον που διατίθεται χωρίς χρέωση και χρησιµοποιείται ευρέως είναι

το Java Development Toolkit ή JDK της Sun του οποίου µια έκδοση µπορεί-

τε να κατεβάσετε από το διαδίκτυο στη διεύθυνση http://java.sun.com/

products/jdk/1.1/index.html. Στη συνέχεια, και µόνο αφού εγκαταστήσετε το

περιβάλλον ανάπτυξης ακολουθώντας τις οδηγίες του κατασκευαστή, µπο-

ρείτε να προχωρήσετε στη µελέτη της ενότητας.

H ενότητα περιγράφει τη διαδικασία ανάπτυξης Java προγράµµατος. Ένα

Java πρόγραµµα µπορεί να έχει µια από τις παρακάτω µορφές:

• Aυτόνοµη εφαρµογή (stand–alone program).

Αποτελεί την κλασσική µορφή προγραµµάτων που γνωρίζετε. Για την εκτέ-

λεση της απαιτείται ο Java διερµηνευτής (interpreter).

• Applet.

Είναι ένα µικρό πρόγραµµα που συνήθως αποθηκεύεται σ’ έναν αποµα-

κρυσµένο υπολογιστή, στον οποίο οι χρήστες µπορούν να συνδεθούν µε τη

χρήση ενός προγράµµατος πλοήγησης για να κατεβάσουν και να εκτελέ-

σουν το applet σαν κοµµάτι µιας ιστοσελίδας. Ένα applet µπορεί να εκτε-

λεστεί εναλλακτικά και από ένα applet viewer[4].

Η διαδικασία ανάπτυξης ενός προγράµµατος Java εξαρτάται από τη µορφή

του και περιγράφεται χωριστά για κάθε περίπτωση στη συνέχεια.

[3] Θα την χαρακτηρίζαµε σαν όχι απόλυτα αντικειµενική.

[4] Eίναι ένας browser µε την ελάχιστη δυνατή λειτουργικότητα που απαιτείται για

την εκτέλεση ενός applet.

Page 29: Γλώσσες Προγραμματισμού II

2.2.1 ¢È·‰Èηۛ· ·Ó¿Ù˘Í˘ ·˘ÙfiÓÔÌ˘ ÂÊ·ÚÌÔÁ‹˜

Η διαδικασία ανάπτυξης αυτόνοµου προγράµµατος σε ένα τυπικό περιβάλ-

λον ανάπτυξης Java εφαρµογών όπως το JDK της Sun περιλαµβάνει τα παρα-

κάτω βήµατα:

1. συγγραφή του πηγαίου κώδικα,

2. µεταγλώττιση του πηγαίου κώδικα,

3. εκτέλεση του προγράµµατος.

Συγγραφή πηγαίου κώδικα

Για τη συγγραφή του πηγαίου κώδικα θα χρησιµοποιήσετε ένα editor της

αρεσκείας σας. Στο Unix µπορείτε, για παράδειγµα, να χρησιµοποιήσετε τον

vi ή τον emacs, ενώ στα Windows Microsoft το Notepad ή ακόµη και τον

DOSEdit. Βέβαια ολοκληρωµένα περιβάλλοντα ανάπτυξης (Integrated

Development Environments – IDEs), όπως το Visual J++ της Microsoft ή το

Visual Cafe της Symantec, έχουν τους δικούς τους εξειδικευµένους editors.

Σε κάθε περίπτωση η αποθήκευση του πηγαίου κώδικα πρέπει να γίνεται σε

αρχείο, του οποίου η επέκταση πρέπει να είναι .java. Προσέξτε! Aν ο editor

σας, προσθέτει διαφορετική επέκταση, πρέπει να τη διορθώσετε.

Μεταγλώττιση

Η µεταγλώττιση γίνεται από τον µεταγλωττιστή της Java που φέρει το όνοµα

javac. Ο µεταγλωττιστής µεταφράζει τον πηγαίο κώδικα Java σε bytecodes,

τη γλώσσα που κατανοεί και εκτελεί ο διερµηνευτής της Java. Θα πρέπει να

παρατηρήσουµε ότι ο µεταγλωττιστής δεν δηµιουργεί εκτελέσιµο κώδικα

της µηχανής εκτέλεσης, αλλά µιας υποθετικής µηχανής που έχει σαν εκτε-

λέσιµο κώδικα τον ονοµαζόµενο bytecodes. Κάθε µηχανή που διαθέτει διερ-

µηνευτή Java µπορεί να θεωρηθεί ιδεατή µηχανή Java (Java virtual machine)

και να εκτελέσει bytecodes.

Για τη µεταγλώττιση θα πρέπει να δοθεί στη γραµµή εντολών του συστήµατός

σας (DOS prompt για Windows 95 ή NT και shell prompt για UNIX) η εντολή:

javac <fiÓÔÌ· ÚÔÁÚ¿ÌÌ·ÙÔ˜>.java

Αν ο µεταγλωττιστής σας εντοπίσει λάθη, τα αναφέρει. ∆ιαφορετικά δηµι-

ουργεί ένα αρχείο[5] µε το όνοµα του προγράµµατος και επέκταση .class, το

2 9¢ π ∞ ¢ π ∫ ∞ ™ π ∞ ∞ ¡ ∞ ¶ ∆ À • ∏ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™ J AVA

[5] Στη συνέχεια θα δούµε πως δηµιουργεί ένα αρχείο για κάθε κλάση του προ-

γράµµατος Java.

Page 30: Γλώσσες Προγραμματισμού II

3 0 ∫ ∂ º ∞ § ∞ π √ 2 : E π ™ ∞ ° ø ° ∏ ™ ∆ ∏ J AVA

οποίο περιέχει την αναπαράσταση του προγράµµατος σε bytecodes και απο-

τελεί το εκτελέσιµο πρόγραµµα.

Εκτέλεση

Η εκτέλεση του προγράµµατος είναι µια σύνθετη διεργασία, διαφορετική

από αυτή των προγραµµάτων των προστακτικών γλωσσών, όπως η C, Pascal

και Fortran. Γίνεται µε τη χρήση του Java διερµηνευτή, τον οποίο ενεργο-

ποιούµε µε την παρακάτω εντολή της γραµµής διαταγών:

java <fiÓÔÌ· ÚÔÁÚ¿ÌÌ·ÙÔ˜>

Προσοχή! ∆εν απαιτείται η προσθήκη της επέκτασης .class.

Με την εκτέλεση του διερµηνευτή της Java το σύστηµα µεταµορφώνεται σε µια

µηχανή που κατανοεί και εκτελεί bytecodes, δηλαδή σε µια ιδεατή µηχανή Java.

Ο διερµηνευτής της Java

O Java διερµηνευτής αποτελείται, όπως φαίνεται και στο σχήµα 2.1, από τα

παρακάτω επί µέρους τµήµατα:

• class loader

Aναλαµβάνει να φορτώσει στη µνήµη του υπολογιστή τον κώδικα bytecode

είτε από το τοπικό σύστηµα αρχείων είτε διαµέσου του δικτύου.

• bytecode verifier

Aναλαµβάνει να ελέγξει κάθε τµήµα (κλάση, όπως θα δούµε στη συνέχεια)

κώδικα bytecode που προέρχεται από το δίκτυο, για να διασφαλίσει ότι δεν

παραβιάζονται οι περιορισµοί ασφαλείας που θέτει το περιβάλλον Java. Είναι

προφανές ότι το περιβάλλον Java πρέπει να έχει περιορισµούς οι οποίοι εµπο-

δίζουν τις εφαρµογές που κατεβάζετε από το δίκτυο να προκαλούν ζηµιές στο

σύστηµά σας (π.χ. διαγραφή αρχείων του δίσκου σας), όταν εκτελούνται.

• interpreter

Tο τελευταίο αυτό τµήµα, που δίνει και το όνοµά του στο όλο πρόγραµµα,

διερµηνεύει τον κώδικα bytecode, εντολή προς εντολή, σε γλώσσα µηχανής

η οποία εκτελείται από την CPU του µηχανήµατος.

H παραπάνω διαδικασία δεν λειτουργεί συνήθως αµέσως. Μετά από κάθε

φάση είναι πιθανό να εντοπιστούν λάθη. Τα λάθη αυτά αναφέρονται από το

σύστηµα, διορθώνονται από τον προγραµµατιστή και η διαδικασία επανα-

λαµβάνεται µέχρι την επιτυχή έκβασή της.

Page 31: Γλώσσες Προγραμματισμού II

¶·Ú¿‰ÂÈÁÌ· 2.1

Αναπτύξτε ένα πρόγραµµα σε Java που θα τυπώνει στην οθόνη το γνωστό

σας πλέον µήνυµα «Hello World».

Στη φάση αυτή δεν µας ενδιαφέρει να κατανοήσετε πλήρως τον κώδικα Java

που δίνεται στο σχήµα 2.2. Αυτό θα γίνει σε επόµενα κεφάλαια. Πρέπει όµως

να εκτελέσετε οπωσδήποτε τη διαδικασία στον υπολογιστή σας µέχρι την

επιτυχή εκτέλεση του προγράµµατος.

public class HelloWorld

static final String message = "Hello World!";

public static void main(String[] arg)

System.out.println(message);

3 1¢ π ∞ ¢ π ∫ ∞ ™ π ∞ ∞ ¡ ∞ ¶ ∆ À • ∏ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™ J AVA

Java source

Xρόνος µεταγλώττισης

Bytecode Loader

Bytecodes

µετακινούνται

διαµέσου του

δικτύου ή του

συστήµατος

αρχείων

Java µεταγλωττιστής

Bytecode Verifier

Java Bytecode

∆ιερµηνευτής

Run time

Yλικό

Code Generator

Xρόνος εκτέλεσης

™¯‹Ì· 2.1.

Ανάπτυξη και εκτέλεση

Java εφαρµογής.

Για την εξοικείωση µε την παραπάνω διαδικασία, χρησιµοποιήστε τον

πηγαίο κώδικα του Παραδείγµατος 1.2 που ακολουθεί για να δηµιουργή-

σετε και να εκτελέσετε µια απλή αυτόνοµη εφαρµογή Java.

¢Ú·ÛÙËÚÈfiÙËÙ· 2.1

™¯‹Ì· 2.2

Πηγαίος κώδικας για το

πρόγραµµα Hello World.

Page 32: Γλώσσες Προγραμματισμού II

3 2 ∫ ∂ º ∞ § ∞ π √ 2 : E π ™ ∞ ° ø ° ∏ ™ ∆ ∏ J AVA

Είναι σηµαντικό να επισηµάνουµε ότι κάθε πρόγραµµα Java πρέπει να περι-

λαµβάνει τον ορισµό µιας τουλάχιστο public κλάσης. Η κλάση αυτή πρέπει

να περιέχει µια συνάρτηση (που καλείται µέθοδος όπως θα δούµε στο επό-

µενο κεφάλαιο) µε όνοµα main, (µην ξεχνάµε πως η Java επηρεάσθηκε από

την C), η οποία πρέπει να είναι public και static. Ο διερµηνευτής της Java

αρχίζει την εκτέλεση του προγράµµατος από τη µέθοδο main. Η main του

παραδείγµατός µας περιέχει µια µόνο πρόταση η οποία έχει σαν αποτέλεσµα

την εκτύπωση στην κύρια έξοδο, του µηνύµατος «Hello World».

Χρησιµοποιήστε, σαν πρώτο βήµα, έναν editor για να γράψετε τον πηγαίο

κώδικα και στη συνέχεια να τον σώσετε σε ένα αρχείο µε όνοµα ίδιο µε αυτό

της public κλάσης του και επέκταση.java. Πρέπει δηλαδή να δηµιουργήσε-

τε το αρχείο HelloWorld.java.

Στη συνέχεια µεταγλωττίστε τον κώδικα Java σε bytecode καλώντας τον java

µεταγλωττιστή της Java:

javac HelloWorld.java

Ο µεταγλωττιστής, αν δεν εντοπίσει λάθη τα οποία πρέπει να διορθώσετε,

παράγει στο τρέχον ευρετήριο το αρχείο HelloWorld.class

Το αρχείο αυτό περιέχει το πρόγραµµα µας σε αναπαράσταση bytecode και

µπορεί να εκτελεστεί σε οποιοδήποτε σύστηµα που διαθέτει διερµηνευτή της

Java. Για την εκτέλεση του προγράµµατος καλέστε το διερµηνευτή Java όπως

παρακάτω:

java HelloWorld

Το αποτέλεσµα θα είναι η εµφάνιση στην οθόνη της γραµµής

HelloWorld!

2.2.2 ¢È·‰Èηۛ· ·Ó¿Ù˘Í˘ Applet

Η διαδικασία ανάπτυξης applet περιλαµβάνει:

1. τη συγγραφή του πηγαίου κώδικα.

Χρησιµοποιήστε ένα editor της αρεσκείας σας π.χ. Notepad.

2. τη µεταγλώττιση του πηγαίου κώδικα σε bytecodes.

Χρησιµοποιήστε το µεταγλωττιστή javac.

3. τη δηµιουργία, µέσα σε µία HTML σελίδα, µιας αναφοράς προς το παρα-

Page 33: Γλώσσες Προγραμματισμού II

γόµενο αρχείο .class

4. την εκτέλεση του applet.

Χρησιµοποιήστε ένα πρόγραµµα πλοήγησης ή ένα applet viewer για να

φορτώσετε την HTML σελίδα που περιέχει την αναφορά στο applet.

3 3¢ π ∞ ¢ π ∫ ∞ ™ π ∞ ∞ ¡ ∞ ¶ ∆ À • ∏ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™ J AVA

Χρησιµοποιήστε τον πηγαίο κώδικα του Παραδείγµατος 2.2 για να δηµι-

ουργήσετε ένα Java applet. Στη συνέχεια δηµιουργήστε µια HTML σελί-

δα, ενσωµατώστε σε αυτή το applet που δηµιουργήσατε και χρησιµοποιή-

στε ένα πρόγραµµα πλοήγησης για να δείτε την εκτέλεση του applet σας.

¢Ú·ÛÙËÚÈfiÙËÙ· 2.2

¶·Ú¿‰ÂÈÁÌ· 2.2

Το πρόγραµµα του οποίου ο πηγαίος κώδικας δίνεται στο σχήµα 2.3, χρησι-

µοποιείται για να δείξει τη διαδικασία παραγωγής και εκτέλεσης ενός applet.

Προς το παρόν δεν θα ασχοληθούµε µε τη σηµασία του πηγαίου κώδικα.

1 // ¶·Ú¿‰ÂÈÁÌ· 1. – ÙÔ ÚÒÙÔ applet

2 import java.applet.Applet; // οÓÂÈ import ÙËÓ ÎÏ¿ÛË

// Applet

3 import java.awt.*; // οÓÂÈ import ÙÔ ·Î¤ÙÔ awt

4

5 public class HelloWorld extends Applet

6 // ∏ ̤ıÔ‰Ô˜ ÂÌÊ·Ó›˙ÂÈ ÙÔ applet.

7 // ∏ ÎÏ¿ÛË Graphics ˘ÔÛÙËÚ›˙ÂÈ ÙȘ ·ÂÈÎÔÓ›ÛÂȘ ÛÙË

// Java.

8 public void paint(Graphics g)

9 g.drawString("Hello World",50, 50);

10

11

™¯‹Ì· 2.3

Πηγαίος κώδικας απλού

Java applet.

Page 34: Γλώσσες Προγραμματισμού II

3 4 ∫ ∂ º ∞ § ∞ π √ 2 : E π ™ ∞ ° ø ° ∏ ™ ∆ ∏ J AVA

Ακολουθήστε προσεκτικά τα παρακάτω βήµατα:

Βήµα 1: Χρησιµοποιήστε τον editor σας για να γράψετε το πρόγραµµα και

να το αποθηκεύσετε στο αρχείο HelloWorld.java. Παραλείψτε την αρίθ-

µηση στο αριστερό άκρο, δεν αποτελεί µέρος του προγράµµατος. Έγινε για

να διευκολύνει την αναφορά στις επιµέρους προτάσεις του προγράµµατος,

όταν στη συνέχεια της ενότητας θα τις σχολιάσουµε µία προς µία.

Βήµα 2: Καλέστε το µεταγλωττιστή για να δηµιουργήσετε την bytecode ανα-

παράσταση

javac HelloWorld.java

Αν ο µεταγλωττιστής δεν ανιχνεύσει λάθη, παράγει το αρχείο

HelloWorld.class. Αν η µεταγλώττιση αποτύχει, διορθώστε τα λάθη

που σας αναφέρει ο µεταγλωττιστής και επαναλάβετε τη διαδικασία. Μια

λίστα µε τα πιθανά λάθη και τις λύσεις τους, µπορείτε να βρείτε στο διαδί-

κτυο στη διεύθυνση http://java.sun.com/docs/books/tutorial/getStarted

/problems/index.html, κάτω από τον τίτλο «Common Compiler and

Interpreter Problems (and Their Solutions)».

Βήµα 3: Για να ενεργοποιήσετε το applet που µόλις κατασκευάσατε, πρέπει

να δηµιουργήσετε σε ένα HTML[6] αρχείο, µια αναφορά προς αυτό. Μπο-

ρείτε να δηµιουργήσετε ένα HTML αρχείο ακολουθώντας έναν από τους

παρακάτω δύο τρόπους:

α) Χρησιµοποιήστε ένα text editor για να δηµιουργήσετε ένα αρχείο µε

όνοµα Hello.html, στο ίδιο ευρετήριο µε αυτό που βρίσκεται το αρχείο

HelloWorld.class που µόλις δηµιουργήσατε. Το αρχείο θα πρέπει να

περιέχει το παρακάτω κείµενο:

<HTML>

<HEAD>

<TITLE> ŒÓ· ·Ïfi applet </TITLE>

</HEAD>

<BODY>

[6] H HTML (Hypertext Markup Language) χρησιµοποιείται για τη διαµόρφωση

ιστοσελίδων του διαδικτύου, οι οποίες είναι κατανοητές από προγράµµατα πλοήγη-

σης, όπως το Communicator της Netscape, το Internet Explorer της Microsoft και

το HotJava της Sun.

Page 35: Γλώσσες Προγραμματισμού II

∞ÎÔÏÔ˘ı› Ë ¤ÍÔ‰Ô˜ ÙÔ˘ ·ÏÔ‡ Java applet:

<APPLET CODE="HelloWorld.class" WIDTH=350 HEIGHT=200>

</APPLET>

</BODY>

</HTML>

β) Μπορείτε εναλλακτικά να δηµιουργήσετε µια HTML σελίδα από τον κει-

µενογράφο Word της Microsoft. ∆ιαµορφώστε το περιεχόµενο µιας σελίδας

του Word µε τις πληροφορίες που θέλετε να περιέχει η σελίδα. Σώστε το κεί-

µενο σας σαν «HTML document» και στη συνέχεια εισάγετε (επιλέξτε

«Insert HTML tag») την παρακάτω αναφορά για την εµφάνιση του applet:

<APPLET CODE="HelloWorld.class" WIDTH=350 HEIGHT=200>

</APPLET>

Η αναφορά αυτή ορίζει το όνοµα του applet, καθώς και τις διαστάσεις σε

pixels της περιοχής του παραθύρου του προγράµµατος πλοήγησης στο οποίο

θα ανατεθεί στο applet. Σώστε τη σελίδα σας σε ένα αρχείο µε το όνοµα

Hello.html.

Βήµα 4: Για να εκτελέσετε το applet θα πρέπει να φορτώσετε τη σελίδα σας

(δηλαδή το αρχείο Hello.html) σε ένα πρόγραµµα πλοήγησης ή applet

viewer[7]. Όταν ο browser ή ο applet viewer εντοπίσει στην HTML σελίδα

µια αναφορά σε ένα applet, ενεργοποιεί τον Java class loader για να φορτώ-

σει το applet. Στη συνέχεια ενεργοποιείται ο bytecode verifier, ο οποίος ελέγ-

χει τον κώδικα του applet για να διασφαλίσει ότι δεν παραβιάζονται οι κανό-

νες ασφάλειας της Java. Τέλος, ο ενσωµατωµένος στο πρόγραµµα πλοήγη-

σης διερµηνευτής εκτελεί το applet µε αποτέλεσµα την εµφάνιση στο παρά-

θυρο του προγράµµατος πλοήγησης του παρακάτω µηνύµατος:

Ακολουθεί η έξοδος του απλού Java applet: Hello World

2.2.3 H ÂÍ‹ÁËÛË ÂÓfi˜ ·ÏÔ‡ Applet

Ας δούµε πώς δουλεύει το applet που µόλις δηµιουργήσατε. Και πρώτ’ απ’

όλα, θα αρχίσουµε από τα σχόλια, τα οποία είναι απαραίτητα σε πολλά

σηµεία για την αύξηση της αναγνωσιµότητας του πηγαίου κώδικα. Χρησι-

3 5¢ π ∞ ¢ π ∫ ∞ ™ π ∞ ∞ ¡ ∞ ¶ ∆ À • ∏ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™ J AVA

[7] Xρησιµοποιήστε την εντολή appletviewer Hello.html για να φορτώσετε την

HTML σελίδα σας στον appletviewer.

Page 36: Γλώσσες Προγραμματισμού II

3 6 ∫ ∂ º ∞ § ∞ π √ 2 : E π ™ ∞ ° ø ° ∏ ™ ∆ ∏ J AVA

µοποιήστε το // για να δείξετε ότι ακολουθούν σχόλια στο υπόλοιπο τµήµα

της γραµµής (γραµµή 2).Καλή προγραµµατιστική τεχνική είναι η τοποθέτη-

ση στην αρχή του προγράµµατος σχολίων τα οποία περιγράφουν τον σκοπό

του προγράµµατος (γραµµή 1).

Θυµόσαστε σίγουρα οτι για την ανάπτυξη οποιασδήποτε σχεδόν εφαρµογής

ήταν απαραίτητη η χρήση της βασικής βιβλιοθήκης της C. Η βιβλιοθήκη

αυτή αποτελείται από ένα σύνολο από καλώς επιλεγµένες συναρτήσεις γενι-

κού σκοπού, που µας διευκολύνουν στην διαδικασία ανάπτυξης. Κάθε συνάρ-

τηση αποτελεί υλοποίηση µιας βασικής διεργασίας. Αντίστοιχα, στην Java,

ένας µεγάλος αριθµός από κλάσεις είναι διαθέσιµος για άµεση χρήση από

τον προγραµµατιστή. Οι κλάσεις είναι οργανωµένες σε κατηγορίες, µε κάθε

κατηγορία να αναφέρεται σαν πακέτο (package). Το σύνολο των πακέτων

είναι γνωστό σαν Java class library ή Java Applications Programming

Interface (Java API). Οι κλάσεις κάθε πακέτου βρίσκονται σε ένα υποευρε-

τήριο κάτω από το ευρετήριο Java του JDK.

Για να χρησιµοποιήσετε µία κλάση θα πρέπει να ενηµερώσετε κατάλληλα

το µεταγλωττιστή, εισάγοντας την κατάλληλη πρόταση import στην αρχή

του προγράµµατός σας. Οι προτάσεις import ενηµερώνουν επιπλέον το µετα-

γλωττιστή για τη θέση των κλάσεων στο σύστηµα σας. Το αλφαριθµητικό

που ακολουθεί τη λέξη κλειδί import, αποτελείται µόνο από το όνοµα του

υποευρετηρίου στο οποίο είναι αποθηκευµένο το πακέτο, οπότε ο µετα-

γλωττιστής αναγνωρίζει ένα πακέτο (το πακέτο awt στην γραµµή 3) ή περι-

λαµβάνει και το όνοµα µιας κλάσης, οπότε ο µεταγλωττιστής αναγνωρίζει

τη συγκεκριµένη κλάση (την κλάση applet στη γραµµή 2).

Ο µεγάλος αριθµός των διαθέσιµων κλάσεων διευκολύνει τον προγραµµα-

τιστή να αναπτύξει σύνθετα προγράµµατα, επαναχρησιµοποιώντας παρά

δηµιουργώντας από το µηδέν κλάσεις. Είναι φανερό λοιπόν, ότι µόνο η

γνώση της γλώσσας δεν είναι πλέον αρκετή για την ανάπτυξη εφαρµογών.

Η καλή γνώση της βασικής βιβλιοθήκης κλάσεων είναι αυτό που αυξάνει την

παραγωγικότητα ενός προγραµµατιστή. Βέβαια, ο προγραµµατιστής έχει επι-

πλέον τη δυνατότητα να αναπτύξει τις δικές του κλάσεις και να τις οργανώ-

σει σε δικά του πακέτα.

Κάθε πρόγραµµα Java αποτελείται από τη δήλωση µιας τουλάχιστον κλά-

σης. Την κλάση αυτή που αναπαριστά το υπό ανάπτυξη πρόγραµµα, ο προ-

γραµµατιστής έχει την δυνατότητα να τη δηλώσει ως νέα κλάση εξ αρχής ή

Page 37: Γλώσσες Προγραμματισμού II

να τη δηλώσει σαν εξειδίκευση µιας από τις ήδη υπάρχουσες (γραµµή 5).

Στη δεύτερη αυτή περίπτωση η νέα κλάση που καλείται υποκλάση (subclass)

ή παραγόµενη (derived) κλάση, κληρονοµεί (inherits) τα χαρακτηριστικά της

προϋπάρχουσας που καλείται βασική κλάση ή super class. Επιπλέον, ο προ-

γραµµατιστής έχει τη δυνατότητα να ορίσει σε αυτή τα δικά του νέα χαρα-

κτηριστικά. Η ιδιότητα αυτή είναι γνωστή σαν κληρονοµικότητα

(inheritance) και αποτελεί ένα από τα µεγαλύτερα πλεονεκτήµατα της ΑΠ.

Ένα πρόγραµµα πλοήγησης για να εκτελέσει ένα applet προϋποθέτει ότι αυτό

έχει ένα σύνολο από χαρακτηριστικά. Θα ήταν δύσκολο για σας να ενσω-

µατώνετε στο κάθε σας applet τα χαρακτηριστικά αυτά, τα οποία, πρώτα απ'

όλα, δεν γνωρίζετε. Η Java προσφέρει τη κλάση applet µε όλα αυτά τα

χαρακτηριστικά και εσείς το µόνο που έχετε να κάνετε είναι να δηλώσετε τη

κλάση σας σαν παραγόµενη από την κλάση applet χρησιµοποιώντας την

έκφραση (γραµµή 5) public class HelloWorld extends ∞pplet.

Στη συνέχεια προσθέτετε τα δικά σας χαρακτηριστικά (γραµµές 6–10) που

έχουν σαν αποτέλεσµα την εκτύπωση του µηνύµατος HelloWorld.

Είναι προφανές, ότι για να χρησιµοποιήσετε τη κλάση applet δεν είναι απα-

ραίτητο να γνωρίζετε την υλοποίησή της. Θα πρέπει όµως να γνωρίζετε τη

διεπαφή της, η οποία και προσδιορίζει τον τρόπο χρήσης των υπηρεσιών που

µπορεί η κλάση και τα στιγµιότυπά της να προσφέρουν.

Οι κλάσεις παίζουν το ρόλο των καλουπιών για την δηµιουργία στιγµιότυ-

πων, τα οποία συνεργαζόµενα θα επιτελέσουν το έργο του προγράµµατός

µας. H λέξη κλειδί public (γραµµή 5) χρησιµοποιείται για να δηλώσει ότι

η κλάση που ακολουθεί είναι µέρος της διεπαφής του προγράµµατός µας µε

το περιβάλλον (κάτι σαν το κουµπάκι «start» του φούρνου µικροκυµάτων).

Το πρόγραµµα πλοήγησης που θα εκτελέσει το applet, πρέπει να βλέπει την

κλάση HelloWorld για να µπορεί να δηµιουργήσει ένα στιγµιότυπό της και

στη συνέχεια να περάσει τον έλεγχο σε αυτό. Το στιγµιότυπο θα εκτελέσει

µε τη σειρά του το έργο του προγράµµατος, θα τυπώσει δηλαδή στην περί-

πτωση µας το «Hello World».

H γραµµή 8, αποτελεί δήλωση µιας µεθόδου. Η µέθοδος έχει τη µορφή της

συνάρτησης της C αλλά προσδιορίζει την συµπεριφορά των στιγµιότυπων

της κλάσης σε ένα από τα µηνύµατα που τα στιγµιότυπα αναγνωρίζουν. Από

το όνοµα, είναι προφανές ότι η εν λόγω µέθοδος προσδιορίζει τη συµπερι-

φορά του στιγµιότυπου στο µήνυµα paint που θα δηµιουργήσει και θα του

3 7¢ π ∞ ¢ π ∫ ∞ ™ π ∞ ∞ ¡ ∞ ¶ ∆ À • ∏ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™ J AVA

Page 38: Γλώσσες Προγραμματισμού II

3 8 ∫ ∂ º ∞ § ∞ π √ 2 : E π ™ ∞ ° ø ° ∏ ™ ∆ ∏ J AVA

αποστείλει το πρόγραµµα πλοήγησης. Το στιγµιότυπο θα λάβει το µήνυµα

και θα συµπεριφερθεί όπως ορίζει η µέθοδος paint. Θα εκτελέσει δηλαδή

το σύνολο των προτάσεων από τις οποίες αποτελείται η µέθοδος και δεν θα

επιστρέψει τίποτε, όπως ορίζει η λέξη κλειδί void. Όπως βλέπετε η µέθο-

δος paint έχει δηλωθεί public, αφού πρέπει να έχει πρόσβαση σε αυτή (δια-

µέσου του µηνύµατος paint) το πρόγραµµα πλοήγησης. ∆έχεται δε σαν όρι-

σµα το g, το οποίο είναι στιγµιότυπο της κλάσης Graphics της βασικής

βιβλιοθήκης.

H εκτέλεση της µεθόδου paint έχει σαν αποτέλεσµα την αποστολή του

µηνύµατος drawString στο στιγµιότυπο g (γραµµή 9). Η συµπεριφορά του

g στο µήνυµα αυτό προσδιορίζεται από την αντίστοιχου ονόµατος µέθοδο

που ορίζει η κλάση Graphics.

Η µέθοδος drawString στην απλή της µορφή δέχεται σαν ορίσµατα ένα

αλφαριθµητικό και τις συντεταγµένες στις οποίες θα το τυπώσει, εκφρασµέ-

νες σε pixels µε αρχή την πάνω αριστερή γωνία του παραθύρου.

Ανατρέξατε στο διαδίκτυο, στη διεύθυνση http://java.sun.com/products/

jdk/1.2/docs/ api/index.html για να δείτε κάτω από τον τίτλο «Java TM

Platform 1.2 API Specification» όλη την τεκµηρίωση της βασικής βιβλιοθή-

κης της Java. Αναζητήστε στο πακέτο awt την κλάση Graphics. Εντοπίστε

τις µεθόδους που ζωγραφίζουν µια γραµµή, ένα ορθογώνιο, ένα πολύγωνο

και µία έλλειψη. Αν δεν έχετε πρόσβαση στο διαδίκτυο ανατρέξτε σ’ ένα από

τα πολλά βιβλία που αναφέρονται στη βιβλιοθήκη κλάσεων της Java.

¢Ú·ÛÙËÚÈfiÙËÙ· 2.3

Τροποποιήστε το applet του παραδείγµατος 2 ώστε να τυπώνει στην οθόνη

το όνοµα, το επώνυµο και την διεύθυνση σας, σε µία γραµµή το καθένα.

Εκτελέστε το και ελέγξτε την σωστή λειτουργία του. Μια δική µας έκδο-

ση θα βρείτε στο τέλος του κεφαλαίου.

¢Ú·ÛÙËÚÈfiÙËÙ· 2.4

∆ηµιουργήστε ένα applet το οποίο θα ζωγραφίζει α) ένα ορθογώνιο µε

πάνω αριστερή γωνία στο σηµείο (10, 20), πλάτος 100 και ύψος 150, β) την

διαγώνιο της πάνω αριστερής γωνίας του παραπάνω ορθογωνίου και γ) µια

έλλειψη που περικλείεται και εφάπτεται των πλευρών του ορθογωνίου.

Αφού ολοκληρώσετε ανατρέξτε στο τέλος του κεφαλαίου για να δείτε µια

δική µας έκδοση.

¢Ú·ÛÙËÚÈfiÙËÙ· 2.5

Page 39: Γλώσσες Προγραμματισμού II

™‡ÓÔ„Ë

Στο κεφάλαιο αυτό, αφού αναφερθήκαµε εν συντοµία στην ιστορία της Java

και τους λόγους που µας ώθησαν στην επιλογή της, περιγράψαµε τη διαδι-

κασία ανάπτυξης Java αυτόνοµης εφαρµογής αλλά και Java applet. Αναφέ-

ραµε τον τρόπο µε τον οποίο µπορείτε να κάνετε πιο ζωντανές τις ιστοσελί-

δες σας, ενσωµατώνοντας σε αυτές Java applets.

Εξοικειωθήκατε µε τα εργαλεία που υποστηρίζουν τη διαδικασία ανάπτυξης

ώστε στη συνέχεια να τα χρησιµοποιείτε σχεδόν µηχανικά. Τέλος µέσα από

την ερµηνεία του κώδικα του απλού applet, του πρώτου παραδείγµατος, ανα-

φέραµε ορισµένες πολύ βασικές αρχές λειτουργίας ενός προγράµµατος Java.

BÈ‚ÏÈÔÁÚ·Ê›·[1] [Sun 95]

James Gosling, Henr McGilton, «The Java Language Environment – A

White Paper» SUN Microsystems 1995.

[2] [Sutherland 95]

Jeff Sutherland «Smalltalk, C++ and OO COBOL: The good the bad

and the ugly», OBJECT MAGAZINE May 95.

3 9™ Y N O æ H / B I B § I O ° PA º I A

Αναφερόµενοι στον πηγαίο κώδικα του σχήµατος 2.3 αντιστοιχίστε τις

λέξεις της αριστερής και της δεξιάς στήλης, στους προσδιορισµούς της

ενδιάµεσης στήλης του παρακάτω πίνακα.

import λέξη κλειδί extends

applet κλάση συστήµατος Applet

awt κλάση προγραµµατιστή paint

public πακέτο Graphics

class στιγµιότυπο g

HelloWorld µέθοδος drawString

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘2.1

Page 40: Γλώσσες Προγραμματισμού II
Page 41: Γλώσσες Προγραμματισμού II

KÏ¿ÛË Î·È AÓÙÈΛÌÂÓÔ

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να παρουσιάσει τον τρόπο που η Java υποστη-

ρίζει τις έννοιες της κλάσης και του στιγµιότυπου για τη δηµιουργία προ-

γραµµάτων αποτελούµενων από σύνολα αλληλεπιδρόντων αντικειµένων.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• αναφέρετε 5 τουλάχιστο κλάσεις και να τις δηλώσετε χωρίς να δίνετε στη

φάση αυτή τα σώµατα των µεθόδων,

• γράψετε τις απαραίτητες προτάσεις για την δηµιουργία 2 τουλάχιστον αντι-

κειµένων για καθεµιά από τις παραπάνω κλάσεις,

• δώσετε από 2 τουλάχιστον προτάσεις αποστολής µηνύµατος στα παραπά-

νω αντικείµενα,

• εξηγήσετε πότε έχουµε πρόσβαση στα δεδοµένα µιας κλάσης και πότε όχι

και να δώσετε για κάθε περίπτωση ένα τουλάχιστο παράδειγµα,

• εξηγήσετε πώς µια αντικειµενοστρεφής γλώσσα επιτυγχάνει την απόκρυ-

ψη πληροφορίας,

• εξηγήσετε πώς οι αντικειµενοστρεφείς γλώσσες υλοποιούν την απόκρυψη

πληροφορίας,

• ορίσετε 2 τουλάχιστο δηµιουργούς για τις κλάσεις που ορίσατε παραπάνω,

• εξηγήσετε πώς η ΑΠ επιτρέπει σε δύο ή περισσότερες µεθόδους να έχουν

το ίδιο όνοµα,

• εξηγήσετε τί σηµαίνει δυναµική διασύνδεση (dynamic binding),

• περιγράψετε τη διαφορά µεταξύ µεταβλητής στιγµιοτύπου και µεταβλητής

κλάσης,

• περιγράψετε τη διαφορά µεταξύ µεθόδου στιγµιοτύπου και µεθόδου κλάσης,

• ορίσετε για δύο τουλάχιστο κλάσεις από 2 µεταβλητές και 2 µεθόδους κλάσης.

3∫ ∂ º ∞ § ∞ π √

Page 42: Γλώσσες Προγραμματισμού II

• κλάση

• στιγµιότυπο

• µέθοδος

• ενθυλάκωση (encapsulation)

• τελεστής this

• τελεστής static

• τελεστής final

• απόκρυψη πληροφορίας

(information hidding)

• αφαίρεση (abstraction)

• δηµιουργός (constructor)

• υπερφόρτωση µεθόδων

(method overloading)

• µεταβλητή κλάσης

(class variable)

• µέθοδος κλάσης (class method)

• δυναµική διασύνδεση

(dynamic binding)

ŒÓÓÔȘ–∫ÏÂȉȿ

4 2 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Ένα πρόγραµµα, που έχει αναπτυχθεί σύµφωνα µε την ΑΠ, αποτελείται κατά

το χρόνο µεταγλώττισης (compile time), από ένα σύνολο ορισµών κλάσεων,

κατά το δε χρόνο εκτέλεσης (run time), από ένα σύνολο από αντικείµενα

(κλάσεις και στιγµιότυπα), τα οποία αλληλεπιδρούν µεταξύ τους, ανταλλάσ-

σοντας µηνύµατα, για να παρέχουν τις εξυπηρετήσεις που το πρόγραµµα προ-

σφέρει. Κλάση και στιγµιότυπο αποτελούν τα βασικά δοµικά στοιχεία από τα

οποία συντίθεται ένα πρόγραµµα.

Το κεφάλαιο αυτό αποτελείται από τέσσερις ενότητες. Η πρώτη ενότητα, χρη-

σιµοποιεί τη γνωστή σας έννοια του σωρού για να εισάγει την κλάση σαν

µηχανισµό της γλώσσας, για την υλοποίηση αφηρηµένου τύπου δεδοµένων

(Abstract Data Type – ADT). Η δεύτερη ενότητα, παρουσιάζει την κλάση και

τον τρόπο δήλωσής της στη Java. Η Τρίτη, αναφέρεται στη δηµιουργία στιγ-

µιότυπων. Τέλος, η τέταρτη ενότητα, αναφέρεται στον τρόπο µε τον οποίο η

Java χειρίζεται µεταβλητές και µεθόδους που δεν χαρακτηρίζουν τα στιγµιό-

τυπα, αλλά τις κλάσεις, προσδίδοντας συµπεριφορά σ’ αυτές.

Το κεφάλαιο θέλει ιδιαίτερη προσοχή, γιατί αποτελεί τη βάση του αντικειµε-

νοστρεφούς προγραµµατισµού. Η σε βάθος κατανόηση των βασικών εννοι-

ών που εισάγει αποτελεί αναγκαία προϋπόθεση για την παραπέρα µελέτη του

βιβλίου. Πριν προχωρήσετε στη µελέτη του κεφαλαίου, είναι σκόπιµο να αφιε-

ρώστε λίγο χρόνο για να εκτελέσετε την ∆ραστηριότητα 1. Θα σας βοηθήσει

στην κατανόηση της Ενότητας 3.1 η οποία καλό είναι να διαβαστεί και µετά

την ολοκλήρωση όλου του κεφαλαίου.

Page 43: Γλώσσες Προγραμματισμού II

3.1 °È·Ù› ÎÏ¿ÛË Î·È ÛÙÈÁÌÈfiÙ˘Ô;

Θα εισάγουµε τις έννοιες της κλάσης και του στιγµιότυπου χρησιµοποιώ-

ντας τη γνωστή σε σας έννοια του σωρού (stack). Ο σωρός, όπως ήδη γνω-

ρίζετε, είναι ένας αποθηκευτικός χώρος όπου µπορούµε να βάζουµε και να

βγάζουµε στοιχεία, µε τον περιορισµό ότι βγαίνει πρώτο αυτό που µπήκε

τελευταίο (Last In – First Out/LIFO). Τον σωρό χρησιµοποιήσαµε στο παρά-

δειγµα της αριθµοµηχανής Πολωνικής σηµειογραφίας, για την προσωρινή

αποθήκευση των τελεστέων. Για την υλοποίηση της έννοιας του σωρού σε

µια διαδικαστική (procedural) γλώσσα, όπως η C:

α) αναγνωρίζουµε και αναπαριστούµε µε συναρτήσεις τις βασικές διεργα-

σίες push(), pop(), is_empty() και clear(),

β) αναπαριστούµε τον αποθηκευτικό χώρο είτε µ’ έναν πίνακα του τύπου

των δεδοµένων που θέλουµε να εισάγουµε και ένα δείκτη στην πρώτη

ελεύθερη θέση π.χ. int buf[100]; και int *buf_ptr=buf;, ή εναλ-

λακτικά δηλώνοντας µια δοµή σωρού και στη συνέχεια µια µεταβλητή

τύπου σωρού, π.χ. struct stack int buf[100];

int*buf_ptr=buf; s1;

Ένα σηµαντικό πρόβληµα που εισάγει η θεώρηση αυτή είναι, ότι το σύνολο

των συναρτήσεων πρέπει να έχει πρόσβαση σε όλα τα δεδοµένα του σωρού,

τα οποία αναγκαστικά δηλώνονται σα γενικές µεταβλητές. Αυτό όµως επι-

τρέπει και σε άλλες συναρτήσεις του προγράµµατος να έχουν πρόσβαση στα

δεδοµένα αυτά. Για να περιορίσουµε την ορατότητα των δεδοµένων του

σωρού, θυµόσαστε ότι δηµιουργήσαµε ένα ξεχωριστό αρχείο, το οποίο ονο-

µάσαµε stack.c. Στο αρχείο αυτό τοποθετήσαµε αφενός µεν τα δεδοµένα τα

οποία δηλώσαµε σαν static, περιορίζοντας έτσι την ορατότητά τους µόνο στο

αρχείο αυτό, αφετέρου δε τις συναρτήσεις, τις οποίες αφήσαµε να έχουν

4 3° π ∞∆ π ∫ § ∞ ™ ∏ ∫ ∞ π ™ ∆ π ° ª π √ ∆ À ¶ √ ;

Ανατρέξτε στο παράδειγµα της αριθµοµηχανής Πολωνικής σηµειογραφίας

του κεφαλαίου «Οργάνωση Προγράµµατος», της Υποενότητας «Γλώσσες

Προγραµµατισµού» και µελετήστε τον τρόπο χρήσης του σωρού (stack).

Στη συνέχεια δηµιουργήστε ένα C πρόγραµµα που να επιτρέπει στον χρή-

στη α) να εισάγει ακέραιο στο σωρό, β) να εξάγει ακέραιο, γ) να καθαρίζει

το σωρό, δ) να βλέπει τα περιεχόµενα του, και ε) να ελέγχει αν ο σωρός

είναι άδειος.

¢Ú·ÛÙËÚÈfiÙËÙ· 3.1

Page 44: Γλώσσες Προγραμματισμού II

4 4 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

καθολική ορατότητα. Χρησιµοποιήσαµε δηλαδή το αρχείο για να οµαδο-

ποιήσουµε δεδοµένα και διεργασίες και να προσδιορίσουµε τους κανόνες

πρόσβασής τους. Πολύ καλό! Παραµένει όµως δύσκολη η δηµιουργία και

διαχείριση ενός δεύτερου ή τρίτου σωρού.

Ας θεωρήσουµε τώρα την προσέγγιση κατά την οποία ο σωρός αντιµετωπί-

ζεται σαν ενεργή οντότητα που έχει µεταβλητές για αποθήκευση των δεδο-

µένων (αναπαράσταση του αποθηκευτικού χώρου) αλλά και συµπεριφορά

(αναπαράσταση των βασικών διεργασιών). Κάθε στιγµιότυπο αυτής της

οντότητας µπορεί να δεχτεί µηνύµατα για να εισάγει ή εξάγει στοιχείο, να

ενηµερώσει αν είναι άδειο ή να αδειάσει τα περιεχόµενά του. Η συµπεριφο-

ρά του στιγµιότυπου για καθένα από τα παραπάνω µηνύµατα περιγράφεται

από µια συνάρτηση ανάλογη αυτών που είχαµε στην παραδοσιακή υλοποί-

ηση. Όταν το στιγµιότυπο δεχτεί το µήνυµα «βγάλε», θα συµπεριφερθεί όπως

ορίζει η συνάρτηση pop(). Αντίστοιχα για το µήνυµα «βάλε», θα συµπερι-

φερθεί όπως ορίζει η συνάρτηση push(). Το σύνολο των τιµών των µετα-

βλητών του στιγµιότυπου αποτελεί την κατάστασή του, οι δε συναρτήσεις

που στη συνέχεια θα τις καλούµε µεθόδους (methods) αποτελούν τους µηχα-

νισµούς πρόσβασης και αλλαγής της κατάστασης του στιγµιότυπου. Οι µετα-

βλητές που αποτελούν την κατάσταση του στιγµιότυπου αλλά και οι µέθο-

δοι που ορίζουν την συµπεριφορά του στα διάφορα µηνύµατα που αυτό δέχε-

ται, θα προσδιορίζονται από την αφηρηµένη έννοια της κλάσης σωρός. Μια

γραφική αναπαράσταση της κλάσης σωρός, αλλά και η αναπαράστασή της

σε κώδικα Java δίνεται στο σχήµα 3.1.

∆εδοµένα

push

po

p

is

empty

class stack

// δεδοµένα κλάσης

private int [] items;

// µέθοδοι

public void push(int) ...

public int pop()...

public boolean isEmpty()...

™¯‹Ì· 3.1.

Η κλάση σωρός

σε γραφική και σε Java

αναπαράσταση.

Page 45: Γλώσσες Προγραμματισμού II

Είναι φανερό ότι εκτός από την οµαδοποίηση δεδοµένων και διεργασιών η

κλάση προσφέρει και µηχανισµό προσδιορισµού της ορατότητας των δεδο-

µένων αλλά και των µεθόδων. Ο µηχανισµός αυτός χρησιµοποιεί τις λέξεις

κλειδιά:

• public για δεδοµένα και µεθόδους που είναι ορατά έξω από την κλάση,

• private για δεδοµένα και µεθόδους που είναι αόρατα έξω από την κλάση.

Έτσι η δήλωση της κλάσης stack του σχήµατος 3.1, προσδιορίζει τα δεδο-

µένα σαν αόρατα έξω από την κλάση, ενώ προσδιορίζει όλες τις µεθόδους

ορατές από τα αντικείµενα του περιβάλλοντος. Αυτό σηµαίνει ότι κανείς

άλλος δεν έχει δυνατότητα αναφοράς στα δεδοµένα παρά µόνο οι µέθοδοι

της κλάσης, διασφαλίζοντας έτσι την ακεραιότητά τους.

Ο ορισµός µιας µεθόδου σαν private γίνεται στην περίπτωση που η µέθοδος

δεν ορίζει συµπεριφορά του αντικειµένου σε µήνυµα του εξωτερικού

κόσµου, αλλά περιγράφει ένα αρκετά γενικό τµήµα επιµέρους συµπεριφο-

ράς που συνήθως χρησιµοποιείται από δύο τουλάχιστον µεθόδους της κλά-

σης. Για παράδειγµα, η µέθοδος private void reportError(), θα µπο-

ρούσε να χρησιµοποιηθεί από τις µεθόδους push και pop για να αναφέρουν

την εµφάνιση τυχόν προβλήµατος.

Είναι ενδιαφέρον να δούµε τη σχέση της κλάσης (class) µε τον τύπο (type).

Ο όρος abstract data type (ADT) χρησιµοποιείται για να προσδιορίσει τις

ιδιότητες ενός τύπου δεδοµένων, αλλά δεν αναφέρεται στο πώς µπορεί ο

τύπος δεδοµένων να αναπαρασταθεί ή υλοποιηθεί. Έτσι, δοθέντος ενός ADT,

µπορούµε να γράψουµε µια κλάση Java που να ικανοποιεί τις προδιαγραφές

που προσδιορίζονται απ’ αυτόν. Ο µηχανισµός ορισµού κλάσεων στην ουσία

επιτρέπει στην Java τον ορισµό νέων τύπων δεδοµένων.

Σαν παράδειγµα, δίνεται στο σχήµα 3.2 η έκφραση του ADT σωρού, όπως

δίνεται στο [Winder 98]. Στο ίδιο βιβλίο και στην ενότητα 3.4 µπορείτε να

ανατρέξετε για µια πιο αναλυτική αναφορά στη σχέση κλάσης τύπου. Μια

πιο πλήρης και αυστηρή έκφραση του ADT σωρού δίνεται και σχολιάζεται

εκτενώς στο [Meyer 88].

4 5° π ∞∆ π ∫ § ∞ ™ ∏ ∫ ∞ π ™ ∆ π ° ª π √ ∆ À ¶ √ ;

Page 46: Γλώσσες Προγραμματισμού II

4 6 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

Nane: Stack of elementType

Operations: create Æ Stack

push(Stack.elementType) Æ Stack

pop(Stack) Æ Stack

top(Stack) Æ elementType

isEmpty(Stack) Æ Stack

Axioms: formal S: Stack and i:elementType

isEmpty(create) = true

isEmpty(push(S,i)) = false

top(create) = error

top(push(S,i)) = I

pop(create)=error

pop(push(S,i)) = S

™¯‹Ì· 3.2

Abstract Data Type(ADT)

του σωρού.

3.2 H ÎÏ¿ÛË ÛÙËÓ Java

3.2.1 ¢‹ÏˆÛË ÎÏ¿Û˘

Υποθέτουµε ότι αναπτύσσουµε ένα πρόγραµµα µε το οποίο ο χρήστης θα

δηµιουργεί στην οθόνη γεωµετρικά σχήµατα και θα τα χειρίζεται, για παρά-

δειγµα θα αλλάζει τη θέση τους, θα τα µικραίνει ή µεγαλώνει, θα τα ταξινο-

µεί σύµφωνα µε το µέγεθος της επιφάνειας ή της περιµέτρου τους, κ.λπ.

Ας ξεκινήσουµε από τον κύκλο και ας προσπαθήσουµε να τον αναπαραστή-

σουµε. Το αντικείµενο του πραγµατικού κόσµου κύκλος, στην πράξη, δεν

µπορεί να δεχτεί µηνύµατα ούτε έχει συµπεριφορά. Παρόλα αυτά αναπαρι-

στούµε την αφηρηµένη έννοια κύκλος σαν κλάση για να εκµεταλλευτούµε

τα πλεονεκτήµατα του ΑΠ. Τα δεδοµένα θα αναπαριστούν την κατάσταση

του κύκλου και οι µέθοδοι την συµπεριφορά του στα µηνύµατα που µπορεί

να δεχτεί. Σε µια πρώτη αναπαράσταση του κύκλου µπορούµε να θεωρή-

σουµε σαν δεδοµένα τις συντεταγµένες (x, y) του κέντρου του και την ακτί-

να του r και σαν πιθανά µηνύµατα που µπορεί να δεχτεί τα «δώσε µου την

περίµετρό σου» και «δώσε µου την επιφάνειά σου». Θα µπορούσαµε να θεω-

ρήσουµε και τα «µετακινήσου στη θέση …», «µεγάλωσε κατά…», κ.λπ. Η

δήλωση της κλάσης κύκλος διαµορφώνεται όπως παρακάτω:

Page 47: Γλώσσες Προγραμματισμού II

public class Circle

aprivate double x,y; // ÔÈ Û˘ÓÙÂÙ·Á̤Ó˜ ÙÔ˘ ΤÓÙÚÔ˘

private double r; // Ë ·ÎÙ›Ó·

// ª¤ıÔ‰ÔÈ Ô˘ ÂÈÛÙÚ¤ÊÔ˘Ó ÙËÓ ÂÚ›ÌÂÙÚÔ Î·È ÙÔ ÂÌ‚·‰fiÓ ÙÔ˘ ·ÎÏÔ˘

public double circumference() return 2* 3.1416*r;

public double area () return 3.1416*r*r;

4 7H ∫ § ∞ ™ ∏ ™ ∆ ∏ ¡ J AVA

Συγκρίνετε την κλάση κύκλος µε τη δοµή κύκλος (struct Circle) της C. ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘3.1

3.2.2 ¢ËÌÈÔ˘ÚÁ›· ÛÙÈÁÌÈfiÙ˘Ô˘

Μετά τη δήλωση της κλάσης µπορούµε να δηλώσουµε µεταβλητές τύπου

κύκλου όπως κάναµε µε τη δοµή Circle στην C ή ακόµη µε τον ενσωµα-

τωµένο τύπο του ακεραίου. Τις µεταβλητές αυτές τις ονοµάζουµε στιγµιό-

τυπα ή αντικείµενα. Η δηµιουργία στιγµιότυπου γίνεται µε τη χρήση του

τελεστή new όπως παρακάτω:

Circle c; // ‰ËÏÒÓÂÈ ÙÔ c Û·Ó fiÓÔÌ· Ô˘ ·Ó·Ê¤ÚÂÙ·È Û ·ÎÏÔ

c = new Circle(); // ·Ó·ı¤ÙÂÈ ÛÙÔ c Ó· ‰Â›¯ÓÂÈ ÙÔ ·ÓÙÈΛÌÂÓÔ Ô˘

// ‰ËÌÈÔ˘ÚÁÂ›Ù·È ·fi ÙËÓ ¤ÎÊÚ·ÛË Ô˘ Â›Ó·È ‰ÂÍÈ¿ ÙÔ˘

// ÙÂÏÂÛÙ‹ ·Ó¿ıÂÛ˘

ή σε πιο συµπαγή µορφή:

Circle c = new Circle( );

στην οποία δηλώνουµε την αναφορά c σε κύκλο και ταυτόχρονα την αρχι-

κοποιούµε να δείχνει στο αντικείµενο που δηµιουργείται από την έκφραση

new Circle( ).

Page 48: Γλώσσες Προγραμματισμού II

4 8 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

[1] Oρισµένοι συγγραφείς θεωρούν πως η Java, όπως και η C++, υλοποιεί το πέρα-

σµα µηνύµατος µε απευθείας αναφορά ή κλήση της µεθόδου που ορίζει την συµπε-

ριφορά του αντικειµένου για το αντίστοιχο µήνυµα.

3.2.3 ¶¤Ú·ÛÌ· ÌËÓ˘Ì¿ÙˆÓ

Στην ΑΠ τα αντικείµενα αλληλεπιδρούν στέλνοντας το ένα στο άλλο µηνύ-

µατα. Ένα αντικείµενο στέλνει ένα µήνυµα σ’ ένα άλλο, ζητώντας την παρο-

χή κάποιας εξυπηρέτησης. Ένα µήνυµα αποτελείται από το όνοµα του µηνύ-

µατος, το οποίο είναι ίδιο µε το όνοµα της µεθόδου που προσδιορίζει τη

συµπεριφορά του αντικειµένου στο µήνυµα, και προαιρετικά από ένα αριθ-

µό ορισµάτων που περικλείονται σε παρενθέσεις. Αυτό σηµαίνει ότι το αντι-

κείµενο αποστολέας πρέπει να γνωρίζει το όνοµα της µεθόδου αλλά και τον

αριθµό και τύπο των ορισµάτων που αυτή δέχεται, καθώς και τον τύπο της

απάντησης που θα λάβει. Και βέβαια, θα πρέπει να µπορεί να αναφερθεί στο

αντικείµενο παραλήπτη για να του αποστείλει το µήνυµα. Το αντικείµενο

παραλήπτης από την άλλη µεριά, αποφασίζει ποια µέθοδο θα εκτελέσει, εντο-

πίζοντας ποιά από τις µεθόδους, που η κλάση του ορίζει, ταιριάζει µε το

όνοµα του µηνύµατος και τα ορίσµατά του. Η διαδικασία αυτή γνωστή σαν

δυναµική διασύνδεση (dynamic binding), αποτελεί ένα από τα ισχυρά στοι-

χεία του ΑΠ µε πλεονεκτήµατα που θα δούµε σε επόµενο κεφάλαιο.

Η αποστολή µηνύµατος έχει την µορφή[1]:

<αναφορά αντικειµένου>.<όνοµα µηνύµατος>([λίστα παραµέτρων]).

Έτσι εάν ένα αντικείµενο θέλει να µάθει την επιφάνεια του κύκλου c θα πρέ-

πει να του στείλει το µήνυµα area. Αυτό γίνεται µε την έκφραση c.area().

Ο αποστολέας χρειάζεται να γνωρίζει µόνο τον τύπο της απάντησης που θα

πάρει στο µήνυµα που έστειλε. Στην περίπτωσή µας θα πάρει σαν απάντη-

ση την επιφάνεια σαν αριθµό κινητής υποδιαστολής διπλής ακρίβειας. ∆εδο-

µένου δε ότι δεν αποδόθηκε τιµή στην ακτίνα του κύκλου και άρα αυτή είναι

0, η επιφάνεια και άρα η επιστρεφόµενη τιµή θα είναι 0.0.

Προσέξτε την έκφραση c.area() και συγκρίνετέ την µε την ισοδύναµη

area ( c ) του διαδικαστικού προγραµµατισµού. Είναι προφανές ότι πρω-

τεύοντα ρόλο στην πρώτη περίπτωση διαδραµατίζει το c, ένα αντικείµενο

τύπου Circle, ενώ στην δεύτερη η συνάρτηση area(struct Circle). Η

µέθοδος στην ΑΠ δεν απαιτεί σαν όρισµα το αντικείµενο στο οποίο θα δρά-

σει, αφού θεωρείται, όπως φαίνεται και από τον ορισµό της ότι ενεργεί πάνω

Page 49: Γλώσσες Προγραμματισμού II

στο στιγµιότυπο της κλάσης στο οποίο αποστέλλεται το µήνυµα. Στη συγ-

γραφή του σώµατος της µεθόδου area() χρησιµοποιείται το δεδοµένο r της

κλάσης, θεωρώντας ότι αυτό είναι η εκάστοτε ακτίνα του στιγµιότυπου που

δέχεται το µήνυµα.

Έτσι, αν έχουµε το στιγµιότυπο c1 µε ακτίνα 1 και το c2 µε ακτίνα 2 οι τιµές

που επιστρέφει η µέθοδος area() θα είναι

Παράσταση Τιµή

c1.area() 3.1416*1*1

c2.area() 3.1416*2*2

Προσοχή !!! Όπως είναι φανερό από τα παραπάνω δεν έχει νόηµα να καλέ-

σουµε µια µέθοδο χωρίς την αναφορά σε συγκεκριµένο στιγµιότυπο. Για

παράδειγµα δεν έχει νόηµα η έκφραση area(). ∆εν µπορούµε επίσης να

γράψουµε c.move(), γιατί δεν έχουµε προσδιορίσει τη συµπεριφορά του

κύκλου για το µήνυµα move, ή µε άλλα λόγια η κλάση Circle δεν έχει ορι-

σµένη τη µέθοδο move. ∆εν µπορώ επίσης να έχω πρόσβαση στα δεδοµένα

του κύκλου c, όπως είχα στα δεδοµένα µιας δοµής. Έτσι στην πρόταση:

c.r = 2.0; //‰ÂÓ ÂÈÙÚ¤ÂÙ·È ·Ó·ÊÔÚ¿ ÛÙËÓ private

//ÌÂÙ·‚ÏËÙ‹ r

ο µεταγλωττιστής Java θα αναγνωρίσει λάθος. Και αυτό γιατί η ακτίνα του

κύκλου έχει δηλωθεί private περιορίζοντας την ορατότητά της στο εσωτερικό

της κλάσης. ∆ικαιολογηµένα τώρα θα αναρωτηθείτε «και πώς θα δώσουµε τιµή

στην ακτίνα του κύκλου αλλά και στο κέντρο του;» Υπάρχουν δύο τρόποι.

Σύµφωνα µε τον πρώτο, τον καθαρά αντικειµενοστρεφή, τα δεδοµένα µιας

κλάσης πρέπει να αποκρύπτονται στο εσωτερικό της (encapsulated) και να

είναι ορατά µόνο από τις µεθόδους της. Θα πρέπει εποµένως να ορίσω

κατάλληλες µεθόδους διαµέσου των οποίων θα έχω πρόσβαση στα δεδοµέ-

να του στιγµιότυπου. Την τεχνική αυτή θα χρησιµοποιήσουµε στην Υποε-

νότητα 3.3.2, όταν θα ορίσουµε δηµιουργό για την κλάση κύκλος. Προς το

παρόν ας δούµε το δεύτερο τρόπο.

3.2.4 ¶ÚÔۤϷÛË ÛÙ· ‰Â‰Ô̤ӷ ·ÓÙÈÎÂÈ̤ÓÔ˘

Μπορούµε να δηλώσουµε τα δεδοµένα µιας κλάσης σαν public[2] παρότι

4 9H ∫ § ∞ ™ ∏ ™ ∆ ∏ ¡ J AVA

[2] Oι καθαρά αντικειµενοστρεφείς γλώσσες όπως η Smalltalk, δεν επιτρέπουν κάτι

τέτοιο, θεωρούν τα δεδοµένα χωρίς δυνατότητα πρόσβασης από το εξωτερικό.

Page 50: Γλώσσες Προγραμματισμού II

5 0 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

αυτό δεν είναι σύµφωνο µε την αυστηρή ΑΠ:

public class Circle

// ‰‹ÏˆÛË ‰Â‰Ô̤ӈÓ

public double x,y;

public double r;

// Ë ‰‹ÏˆÛË ÙˆÓ ÌÂıfi‰ˆÓ ‰ÂÓ ·ÏÏ¿˙ÂÈ

Η αναφορά σε public δεδοµένα γίνεται όπως ακριβώς και στα µέλη της

δοµής. Οι προτάσεις του πηγαίου κώδικα του σχήµατος 3.3 δηµιουργούν τον

κύκλο c και αποδίδουν τιµή στα δεδοµένα του:

Circle c = new Circle ( ); //‰ËÌÈÔ˘ÚÁԇ̠ÙÔÓ Î‡ÎÏÔ c

// ·Ú¯ÈÎÔÔÈԇ̠ÙÔÓ Î‡ÎÏÔ Ì·˜ Ó· ¤¯ÂÈ Î¤ÓÙÚÔ (10,20) ηÈ

// ·ÎÙ›Ó· 2.0.

c.x = 10.0;

c.y = 20.0;

c.r = 2.0;

3.2.5 ∂Óı˘Ï¿ÎˆÛË

Το γεγονός ότι από ένα αντικείµενο βλέπω µόνο τα στοιχεία διαµέσου των

οποίων αυτό επικοινωνεί µε το περιβάλλον του, οφείλεται στο ότι η κλάση

παρέχει ένα µηχανισµό για την απόκρυψη πληροφορίας (information hiding).

Με τον τρόπο αυτό επιτυγχάνεται η ανεξαρτησία της εφαρµογής που χρησι-

µοποιεί ένα αντικείµενο, από τον τρόπο υλοποίησης του αντικειµένου ή µε

άλλα λόγια ο δραστικός διαχωρισµός του χρήστη του αντικειµένου από τον

κατασκευαστή του. Βέβαια, ο περιορισµός που τίθεται στην περίπτωση αυτή

είναι ότι ο χρήστης µπορεί να χρησιµοποιήσει το αντικείµενο µόνο διαµέ-

σου των µηνυµάτων που ο κατασκευαστής υποστηρίζει.

Η έννοια ξεκινά από το data abstraction ή modular programming που υπο-

στηρίζεται από τις γλώσσες Modula–2 (modules) και Ada (packages), ενώ

δεν υποστηρίζεται από γλώσσες όπως Pascal και C. Για τη Java, όπως και

για τη C++, η υποστήριξη της ενθυλάκωσης (encapsulation) παρέχεται από

το µηχανισµό της κλάσης.

™¯‹Ì· 3.3

∆ηµιουργία και αρχικο-

ποίηση στιγµιότυπου.

Page 51: Γλώσσες Προγραμματισμού II

¶·Ú¿‰ÂÈÁÌ· 3.1

Να αναπτυχθεί πρόγραµµα το οποίο να δηµιουργεί δύο κύκλους µε κέντρα

(2.0, 2.0) και (5.0, 2.0) και ακτίνες 3.0 και 2.0 αντίστοιχα και στη συνέχεια

να τυπώνει τις επιφάνειες και περιµέτρους τους.

Το πρόγραµµά µας, του οποίου ο πηγαίος κώδικας δίνεται στο σχήµα 3.4

είναι απλό, περιέχει δε µόνο δύο κλάσεις. Η µία εξ αυτών είναι η κλάση

κύκλος, για την οποία ήδη αναφέραµε αρκετά. Η άλλη, είναι η κλάση που

αναπαριστά το πρόγραµµά µας. Ας µην ξεχνάµε ότι το πρόγραµµά µας είναι

ένα αντικείµενο το οποίο όταν δεχτεί το µήνυµα «run» θα πρέπει να αντι-

δράσει σ’ αυτό. Τη συµπεριφορά αυτή στο µήνυµα «run» ορίζει η µέθοδος

main της κλάσης CircleTest1, όπως ονοµάσαµε την κλάση που αναπα-

ριστά το πρόγραµµα µας (γραµµή 3) και η οποία προφανώς θα πρέπει να

είναι public. Η αντίδραση που ορίζει η main είναι απλή και συνίσταται στη

δηµιουργία δύο στιγµιότυπων τύπου κύκλου (γραµµές 6 και 11), στην από-

δοση αρχικών τιµών σε αυτά (γραµµές 7–9 και 12) και στην εµφάνιση στην

οθόνη των ζητούµενων περιµέτρων και επιφανειών, που υπολογίζονται από

τα δύο στιγµιότυπα και επιστρέφονται σαν απόκριση στην αποστολή σ’ αυτά

των µηνυµάτων area και circumference (γραµµές 15, 16 και 19, 20). Η

εκτέλεση του προγράµµατός µας ολοκληρώνεται µε την ολοκλήρωση του

σώµατος της µεθόδου main (γραµµή 23) και ο έλεγχος επιστρέφει στο αντι-

κείµενο που έστειλε το µήνυµα «run» στο πρόγραµµά µας.

5 1H ∫ § ∞ ™ ∏ ™ ∆ ∏ ¡ J AVA

Κάντε µια προσπάθεια να δώσετε µε δοµηµένα Ελληνικά την αντικειµε-

νοστρεφή έκδοση του προγράµµατος που αναπτύξατε στην ∆ραστηριότη-

τα 3.1.Τη δική µας άποψη µπορείτε να δείτε στο τέλος του βιβλίου.

¢Ú·ÛÙËÚÈfiÙËÙ·3.2

Page 52: Γλώσσες Προγραμματισμού II

5 2 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

1 // ¶ÚÒÙÔ ·Ú¿‰ÂÈÁÌ· Û Java

2 // ¢‹ÏˆÛË ÎÏ¿Û˘, ‰ËÌÈÔ˘ÚÁ›· ÛÙÈÁÌÈfiÙ˘ˆÓ, ·Ó·ÊÔÚ¿ Û ÌÂÙ·‚ÏËÙ¤˜, ÎÏ‹ÛË

// ÌÂıfi‰ˆÓ

3 public class CircleTest1

4 public static void main(String[] argv)

5 System.out.println("Example 2 running");

6 Circle a = new Circle() // ‰ËÌÈÔ˘ÚÁ›· ·ÎÏÔ˘ a

7 a.x = 2.0; // ·fi‰ÔÛË ÙÈÌÒÓ ÛÙȘ ÌÂÙ·‚ÏËÙ¤˜ ÙÔ˘

// ·ÎÏÔ˘ a

8 a.y = 2.0;

9 a.r = 3.0;

10

11 b.x = 5.0; b.y = 2.0; b.r = 2.0; // ·fi‰ÔÛË ÙÈÌÒÓ ÛÙȘ ÌÂÙ·‚ÏËÙ¤˜

// ÙÔ˘ ·ÎÏÔ˘ b

12 Circle b = new Circle(); // ‰ËÌÈÔ˘ÚÁ›· ·ÎÏÔ˘ b

13

14 System.out.println("1Ô˜ ∫‡ÎÏÔ˜"); // ÂÎÙ‡ˆÛË ÛÙÔȯ›ˆÓ

// ·ÎÏÔ˘ a

15 System.out.println("ÂÚ›ÌÂÙÚÔ˜:" +a.circumference());

16 System.out.println("ÂÈÊ¿ÓÂÈ·:" +a.area() + "\n");

17

18 System.out.println("2Ô˜ ∫‡ÎÏÔ˜"); // ÂÎÙ‡ˆÛË ÛÙÔȯ›ˆÓ

// ·ÎÏÔ˘ b

19 System.out.println("ÂÚ›ÌÂÙÚÔ˜:" +b.circumference());

20 System.out.println("ÂÈÊ¿ÓÂÈ·:" +b.area());

21

22

23

24 class Circle

25 public double x,y,r;

26 public double circumference() return 2* 3.1416*r;

27 public double area() return 3.1416*r*r;

28

™¯‹Ì· 3.4

Πηγαίος κώδικας Παραδείγµατος 3.1

Page 53: Γλώσσες Προγραμματισμού II

3.3 ¢ËÌÈÔ˘ÚÁÔ› ·ÓÙÈÎÂÈ̤ӈÓ

3.3.1 ªË¯·ÓÈÛÌfi˜ ‰ËÌÈÔ˘ÚÁ›·˜ ÛÙÈÁÌÈfiÙ˘Ô˘

Ας ξαναδούµε την πρόταση της δηµιουργίας ενός στιγµιότυπου της κλάσης

κύκλος:

Circle c = new Circle ( );

Η πρόταση περιλαµβάνει την αποστολή του µηνύµατος new στην κλάση

Circle για να της ζητήσει τη δηµιουργία ενός στιγµιοτύπου της. Παρατη-

ρήστε ότι, αφενός ο τρόπος αποστολής του µηνύµατος είναι διαφορετικός απ’

αυτόν που είδαµε να χρησιµοποιείται για αποστολή µηνύµατος σε στιγµιό-

τυπο (δες c.area()), αφετέρου, δεν έχουµε ορίσει στην κλάση Circle τη

συµπεριφορά της για ένα τέτοιο µήνυµα. Τί συµβαίνει λοιπόν; Η απάντηση

δίνεται από το σύστηµα ανάπτυξης. H Java διασφαλίζει ότι κάθε κλάση που

δηλώνεται στο περιβάλλον της, έχει τη δυνατότητα να δηµιουργεί στιγµιότυ-

πα µε τον περιορισµό ότι δεν µπορούµε να αποδώσουµε αρχικές τιµές τη στιγ-

µή της δηµιουργίας. Μπορούµε να πούµε ότι το σύστηµα εφοδιάζει κάθε

κλάση µε µια ειδική µέθοδο, την οποία η κλάση καλεί, όταν δέχεται το µήνυ-

µα δηµιουργίας στιγµιότυπου new. Η µέθοδος αυτή, επειδή έχει τη γνώση

δηµιουργίας στιγµιότυπου, ονοµάζεται δηµιουργός (constructor).

Μία από τις βασικές ενέργειες του δηµιουργού, είναι η δέσµευση χώρου στη

µνήµη, για την αποθήκευση των τιµών των δεδοµένων, που η κλάση ορίζει.

Στην περίπτωσή µας, για την αποθήκευση του στιγµιότυπου c δεσµεύεται

µνήµη, η οποία εκτός των άλλων περιέχει και τις τιµές των δεδοµένων που

η κλάση Circle ορίζει, δηλαδή τις συντεταγµένες του κέντρου και την ακτί-

να, µε τη µορφή µεταβλητών τύπου double.

Τέλος, οι παρενθέσεις που ακολουθούν το όνοµα της κλάσης στην οποία

απευθύνεται το µήνυµα δηµιουργίας νέου αντικειµένου, χρησιµεύουν για να

περικλείσουν τις τυχόν αρχικές τιµές που θέλουµε να αποδώσουµε στο νέο

δηµιουργούµενο αντικείµενο. Αυτό το τελευταίο όµως, προϋποθέτει τον ορι-

σµό από µας πλέον του κατάλληλου δηµιουργού.

3.3.2 √ÚÈÛÌfi˜ ‰ËÌÈÔ˘ÚÁÔ‡

Ένας κύκλος έχει δεδοµένο κέντρο και ακτίνα και το πιο λογικό είναι να απο-

δώσω τις τιµές αυτές τη στιγµή της δηµιουργίας της αναπαράστασής του

στον υπολογιστή. Στο σχήµα 3.5 δίνεται ένας δηµιουργός, ο οποίος τη στιγ-

µή της δηµιουργίας αποδίδει και τις θεµιτές αρχικές τιµές.

5 3¢ ∏ ª π √ À ƒ ° √ π ∞ ¡ ∆ π ∫ ∂ π ª ∂ ¡ ø ¡

Page 54: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

Η λέξη κλειδί tthhiiss στο σώµα ενός δηµιουργού αποτελεί την αναφορά για

το στιγµιότυπο που µόλις δηµιουργήθηκε. Με την αναφορά αυτή έχουµε την

δυνατότητα να αναφερθούµε στα δεδοµένα του στιγµιότυπου, αποδίδοντας

αρχικές τιµές. Στο σώµα άλλων µεθόδων µπορεί να χρησιµοποιηθεί, για να

τονίσει, ότι η µέθοδος αναφέρεται στα δεδοµένα του στιγµιότυπου που

δέχτηκε το µήνυµα π.χ.

public double area( ) return 3.1416*this.r*this.r;

Μετά την παραπάνω δήλωση δηµιουργού, η δηµιουργία στιγµιότυπου του

σχήµατος 3.3 θα πάρει την πιο συµπαγή µορφή:

Circle c = new Circle( 10.0, 20.0, 2.0);

Με το νέο δηµιουργό, αφενός η ανάθεση αρχικών τιµών γίνεται κοµµάτι του

βήµατος δηµιουργίας του αντικειµένου, αφετέρου µας δίνεται η δυνατότητα

να ορίσουµε τα δεδοµένα του κύκλου σαν private. Κατά τη δήλωση δηµι-

ουργού θα πρέπει να αποδοθεί προσοχή στα παρακάτω:

1. Ο δηµιουργός πρέπει να έχει οπωσδήποτε το όνοµα της κλάσης.

2. Η χρήση του δηµιουργού παραβιάζει το γενικό κανόνα της κλήσης των

µεθόδων. Η κλήση του είναι ανεξάρτητη από την ύπαρξη ή όχι στιγµιό-

τυπων της κλάσης. Επιπλέον, οι δηµιουργοί δεν καλούνται άµεσα στα

προγράµµατα, αντίθετα, καλούνται έµµεσα κάθε φορά που ζητείται η

δηµιουργία ενός στιγµιότυπου.

5 4

™¯‹Ì· 3.5

∆ήλωση δηµιουργού στην

κλάση κύκλος.

public class Circle

private double x,y,r,// ‰‹ÏˆÛË Î¤ÓÙÚÔ˘ Î·È ·ÎÙ›Ó·˜

ppuubblliicc CCiirrccllee((ddoouubbllee xx,, ddoouubbllee yy,, ddoouubbllee rr)) // ‰‹ÏˆÛË ÌÂıfi‰Ô˘

// ‰ËÌÈÔ˘ÚÁÔ‡

tthhiiss..xx==xx;;

tthhiiss..yy==yy;;

tthhiiss..rr==rr;;

public double circumference( ) return 2*3.1416*r;

public double area( ) return 3.1416*r*r;

Page 55: Γλώσσες Προγραμματισμού II

5 5¢ ∏ ª π √ À ƒ ° √ π ∞ ¡ ∆ π ∫ ∂ π ª ∂ ¡ ø ¡

3. Το σώµα του δηµιουργού χρησιµοποιεί την λέξη κλειδί this, σαν αναφο-

ρά στο στιγµιότυπο που µόλις δηµιουργήθηκε και διαµέσου αυτής προ-

σπελαύνει και αναθέτει τιµές στα δεδοµένα του στιγµιότυπου. Η χρήση του

this δεν είναι απαραίτητη, αν τα ονόµατα των ορισµάτων του δηµιουρ-

γού δεν είναι ίδια µε αυτά που χρησιµοποιούνται στον ορισµό της κλάσης.

4. ∆εν ορίζεται επιστρεφόµενη τιµή, ούτε χρησιµοποιείται η λέξη κλειδί

void, και εποµένως δεν έχει νόηµα να χρησιµοποιηθεί το return.

5. Ο δηµιουργός επιστρέφει έµµεσα την τιµή του τελεστή this. Αυτή είναι

η τιµή που αποδίδεται στην δηλωθείσα αναφορά για το στιγµιότυπο.

Στο ίδιο παράδειγµα διαχείρισης γεωµετρικών σχηµάτων, υπάρχει ανάγκη

αναπαράστασης του ορθογωνίου. Μια απλοποιηµένη αναπαράστασή του

µπορεί να δοθεί µε τις συντεταγµένες σε pixels των δύο διαγώνια απένα-

ντι κορυφών του. ∆ώστε τον ορισµό της κλάσης που αναπαριστά το ορθο-

γώνιο, θεωρώντας ότι θέλουµε απόκριση µόνο στα µηνύµατα area και

circumference. Τη δική µας εκδοχή θα βρείτε στο τέλος του βιβλίου.

¢Ú·ÛÙËÚÈfiÙËÙ·3.3

Γράψτε ένα πρόγραµµα που να υπολογίζει και εµφανίζει στην οθόνη την

επιφάνεια και την περίµετρο ορθογωνίου µε διαγώνια απέναντι κορυφές

τις (20, 20), (60, 80), εκφρασµένες σε pixels. Στη συνέχεια ανατρέξτε στο

τέλος του βιβλίου, για το δικό µας σχολιασµό.

¢Ú·ÛÙËÚÈfiÙËÙ·3.4

+xx2x1

+y

y2

y1

3.3.3 ¶ÔÏÏ·ÏÔ› ‰ËÌÈÔ˘ÚÁÔ›

Μερικές φορές θα θέλετε να µπορείτε να αναθέσετε αρχικές τιµές σε ένα

αντικείµενο µε διαφορετικούς τρόπους, ανάλογα µε το τι είναι βολικό για

την κάθε περίπτωση. Για παράδειγµα, µπορεί να θέλετε να δώσετε αρχική

Page 56: Γλώσσες Προγραμματισμού II

5 6 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

public class Circle

public double x, y, r;

public Circle(double x, double y, double r) // ·Ú¯ÈÎÔÔÈ› fiÏ· Ù·

// ‰Â‰Ô̤ӷ

this.x = x; this.y =y; this.r =r;

ppuubblliicc CCiirrccllee((ddoouubbllee rr)) xx==00..00;; yy==00..00;; tthhiiss..rr==rr;; // ·Ú¯ÈÎÔÔÈ› ÌfiÓÔ

// ·ÎÙ›Ó·

ppuubblliicc CCiirrccllee((CCiirrccllee cc)) xx==cc..xx;; yy==cc..yy;; rr==cc..rr;; // ‰ËÌÈÔ˘ÚÁ› ÎÏÒÓÔ

ppuubblliicc CCiirrccllee(( )) xx==00..00;; yy==00..00;; rr==11..00;; // ‰ËÌÈÔ˘ÚÁ› ·ÎÏÔ

// ΤÓÙÚÔ˘ (0.0,0.0)

// Î·È ·ÎÙ›Ó·˜ 1.0

public double circumference( ) return 2*3.1416*r;

public double area( ) return 3.1416*r*r;

τιµή για την ακτίνα του κύκλου χωρίς να δώσετε τιµή για τη θέση του

κέντρου ή µπορεί να θέλετε να δηµιουργήσετε έναν κλώνο (κύκλο µε δεδο-

µένα ίδια µε αυτά υπάρχοντα κύκλου), κ.λπ. Η ΑΠ εκµεταλλευόµενη το

µηχανισµό της δυναµικής διασύνδεσης που ήδη αναφέραµε, σας επιτρέπει

να δηλώσετε όσους δηµιουργούς θέλετε για µια κλάση, αρκεί αυτοί να δια-

φέρουν στον αριθµό ή τη σειρά ή στον τύπο των ορισµάτων που δέχονται.

Το σχήµα 3.6 δίνει τέσσερις δηµιουργούς για τη κλάση Circle:

™¯‹Ì· 3.6

Πολλαπλοί δηµιουργοί

κύκλου

3.3.4 ÀÂÚÊfiÚÙˆÛË ÌÂıfi‰ˆÓ

Όλοι οι δηµιουργοί, όπως θα προσέξατε, έχουν το ίδιο όνοµα, γεγονός που

σε ένα procedural περιβάλλον, όπως η C, θα δηµιουργούσε προβλήµατα.

Θυµόσαστε σίγουρα ότι σ’ ένα τέτοιο περιβάλλον η συνάρτηση αναγνωρί-

ζεται µοναδιαία από τ’ όνοµά της. Αντίθετα, στη Java, επιτρέπεται να δηλώ-

σουµε µεθόδους µε το ίδιο όνοµα αρκεί αυτές να διαφέρουν στον αριθµό ή

στον τύπο των ορισµάτων που δέχονται. Είναι προφανές, ότι οι µέθοδοι αυτοί

θα έχουν διαφορετικές υλοποιήσεις και κατά συνέπεια η συµπεριφορά του

αντικειµένου σε ένα µήνυµα θα είναι ανάλογη του αριθµού και του τύπου

των παραµέτρων που συνοδεύουν το µήνυµα. Το φαινόµενο αυτό ονοµάζε-

ται υπερφόρτωση µεθόδων (method overloading) και βασίζεται στο χαρα-

Page 57: Γλώσσες Προγραμματισμού II

κτηριστικό της γλώσσας που λέγεται strong typing. Σύµφωνα µ’ αυτό, όλες

οι εκφράσεις που παρέχονται σαν ορίσµατα σ’ ένα µήνυµα, έχουν τους

τύπους τους, οι οποίοι χρησιµοποιούνται σε συνδυασµό µε το όνοµα του

µηνύµατος, στη διαδικασία επιλογής της κατάλληλης για εκτέλεση µεθόδου.

Για να είµαστε πιο ακριβείς, µια µέθοδος στη Java αναγνωρίζεται µοναδιαία

όχι µόνο από τ’ όνοµά της, αλλά και από τον τύπο της επιστρεφόµενης τιµής

της και τον αριθµό, τον τύπο και τη θέση των ορισµάτων της.

Η υπερφόρτωση των µεθόδων είναι µια καλή τεχνική, αρκεί να δίνετε στις

µεθόδους το ίδιο όνοµα, µόνο όταν αυτές εκτελούν παρόµοιες λειτουργίες

µε ελάχιστα διαφορετικά δεδοµένα εισόδου ή εξόδου.

5 7¢ ∏ ª π √ À ƒ ° √ π ∞ ¡ ∆ π ∫ ∂ π ª ∂ ¡ ø ¡

Στη ∆ραστηριότητα 3.3 αναπαραστήσαµε το ορθογώνιο µε δεδοµένα x, y,

w και h και ορίσαµε το δηµιουργό Rectangle(int x, int y, int w, int h). Για να

διευκολύνουµε τη δηµιουργία ορθογωνίου όταν έχουµε τα x1,y1 και x2,y2,

θα µπορούσαµε να δηλώσουµε το δηµιουργό Rectangle(int x1, int y1, int

x2, int y2). Είναι µια τέτοια δήλωση σωστή; Εξηγήστε την απάντηση σας.

ÕÛÎËÛËA˘ÙÔ·ÍÈÔÏfiÁËÛ˘3.2

3.3.5 ∞ÏÔÔÈË̤ÓË Û˘ÁÁÚ·Ê‹ ‰ËÌÈÔ˘ÚÁÒÓ

Ας δούµε πώς µπορεί να απλοποιηθεί η υλοποίηση των δηµιουργών του σχή-

µατος 3.6 µε χρήση του τελεστή this. Το σχήµα 3.7 δίνει µια πιο συµπαγή

έκφραση των δηµιουργών αυτών:

public Circle(double x, double y, double r)

this.x=x; this.y=y; this.r=r;

public Circle(double r) tthhiiss ((00..00,,00..00,,rr));;

public Circle(Circle c) tthhiiss ((cc..xx,, cc..yy,, cc..rr));

public Circle() tthhiiss ((00..00,,00..00,,11..00));;

™¯‹Ì· 3.7

Συγγραφή δηµιουργών µε

χρήση του τελεστή this.

Όπως βλέπετε δεν έχουµε καµία αλλαγή στη διεπαφή των δηµιουργών καθώς

και στην υλοποίηση του πρώτου δηµιουργού. Η υλοποίηση των υπόλοιπων

δηµιουργών τροποποιήθηκε έτσι, ώστε να κάνουν τη δουλειά τους καλώντας

τον αρχικό δηµιουργό. Ο τελεστής this, στο σώµα µιας µεθόδου, ακολου-

θούµενος από παρενθέσεις, µεταφέρει τον έλεγχο στη µέθοδο µε το ίδιο

όνοµα, ο αριθµός δε και ο τύπος των ορισµάτων που τον ακολουθούν προσ-

διορίζουν την συγκεκριµένη υλοποίηση που θα κληθεί.

Page 58: Γλώσσες Προγραμματισμού II

5 8 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

Με τον τρόπο αυτό το σύστηµα υποστηρίζει τη βασική αρχή της επαναχρη-

σιµο–ποίησης και διευκολύνει την υλοποίηση των µεθόδων. Το παράδειγµά

µας δεν είναι σίγουρα το καλύτερο. Θα ήταν πιο εντυπωσιακό, αν ο πρώτος

δηµιουργός τον οποίο καλούµε είχε µια πιο σύνθετη υλοποίηση, κάτι που

συνήθως συµβαίνει στην πράξη.

Θα πρέπει να επισηµάνουµε ότι, η κλήση προϋπάρχουσας υλοποίησης της

µεθόδου µπορεί να αποτελεί µόνο πρώτη πρόταση της νέας µεθόδου και ότι

µετά την κλήση της µπορεί να υπάρχει οποιοσδήποτε αριθµός προτάσεων

για πρόσθετη πιθανή λειτουργικότητα.

Στην εισαγωγή του κεφαλαίου 6 µε τίτλο «∆οµές» ο Kernighan [Kernighan

88], για να αναπαραστήσει τις έννοιες του σηµείου και ορθογωνίου, ορίζει

τις δοµές point και rect αντίστοιχα. Αναπαριστά το µεν σηµείο µε τις δύο

ακέραιες συντεταγµένες του x και y, το δε ορθογώνιο µε ένα ζευγάρι σηµεί-

ων που αντιπροσωπεύουν τις διαγώνια απέναντι κορυφές του. Στη συνέ-

χεια, αναπαριστά µε συναρτήσεις τις διεργασίες: δηµιουργία σηµείου

(makepoint), πρόσθεση δύο σηµείων (addpoint), έλεγχο για το αν ένα

σηµείο βρίσκεται µέσα σ’ ένα ορθογώνιο (ptinrect) και κανονικοποίηση

των συντεταγµένων ορθογωνίου (canonrect). Αφού µελετήσετε τις παρα-

πάνω δοµές και συναρτήσεις, αναπαραστήστε τις ίδιες έννοιες (σηµείο,

ορθογώνιο και διεργασίες) χρησιµοποιώντας ΑΠ. Τη δική µας προσέγγιση

θα βρείτε στο τέλος του βιβλίου.

¢Ú·ÛÙËÚÈfiÙËÙ·3.5

3.4 MÂÙ·‚ÏËÙ¤˜ Î·È Ì¤ıÔ‰ÔÈ ÎÏ¿Û˘

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Ας θεωρήσουµε πάλι τη διαδικασία αναπαράστασης της αφηρηµένης έννοι-

ας κύκλος από µια κλάση. Ονοµάσαµε την κλάση Circle και αναπαραστήσα-

µε τα µεν δεδοµένα της µε τις µεταβλητές x ,y και r, την δε συµπεριφορά της

στα µηνύµατα που θέλουµε να δέχεται και να αναγνωρίζει, µε τις µεθόδους

area() και circumference(). Θεωρήσαµε την παραπάνω κλάση στα πλαίσια

µιας εφαρµογής όπου ο χρήστης έχει τη δυνατότητα να δηµιουργεί γεωµετρι-

κά σχήµατα στην οθόνη και να τα χειρίζεται. Στα πλαίσια µιας τέτοιας εφαρ-

µογής, λογικό είναι να θέλουµε να γνωρίζουµε ανά πάσα στιγµή τον αριθµό

των κύκλων που έχει δηµιουργήσει ο χρήστης.

Page 59: Γλώσσες Προγραμματισμού II

Θέλουµε έναν απαριθµητή θα µου πείτε. Πολύ απλό! Θα δηλώσουµε µια

µεταβλητή count και θα φροντίσουµε, κάθε φορά που ο χρήστης δηµιουργεί

έναν κύκλο και άρα στο πρόγραµµά µας δηµιουργείται ένα στιγµιότυπο, να

αυξάνουµε τον απαριθµητή.

Πολύ ωραία! Και προφανώς ο απαριθµητής θα είναι ακέραια µεταβλητή και

η δήλωση του απλή int count;. Αν όµως βάλετε την δήλωση αυτή πριν ή µετά

από τη δήλωση της κλάσης Circle, ο µεταγλωττιστής θα αναφέρει λάθος. Η

ΑΠ δεν επιτρέπει και η Java δε δέχεται δήλωση µεταβλητών έξω από το

σώµα δήλωσης κλάσεων ή πιο απλά δε δέχεται δηλώσεις της µορφής των

γενικών µεταβλητών της C. Ας βάλουµε, θα µου πείτε, την παραπάνω δήλω-

ση µαζί µε τις δηλώσεις των µεταβλητών της κλάσης Circle. ∆εν είναι τόσο

άσχηµο. Εξ άλλου η µεταβλητή έχει σχέση µε τον κύκλο. H δήλωση της κλά-

σης τώρα θα διαµορφωθεί όπως παρακάτω:

public class Circle

private double x,y,r;

private count;

// ª¤ıÔ‰ÔÈ ÎÏ¿Û˘

Tι σηµαίνει όµως ο παραπάνω ορισµός; Με τη δηµιουργία του πρώτου στιγ-

µιότυπου θα δεσµευθεί χώρος για την αποθήκευση του κέντρου του, της ακτί-

νας του αλλά, προσέξτε, και του αριθµού των κύκλων. Και αυτό θα συµβαί-

νει σε κάθε στιγµιότυπο που θα δηµιουργείται: Σπατάλη χώρου και όχι µόνο.

Κάθε φορά που θα δηµιουργείται ένα νέο στιγµιότυπο θα πρέπει να ενηµε-

ρώνουµε όλ’ αυτά τα αντίγραφα της count, ώστε να περιέχουν τη σωστή

τιµή. Προφανώς δε θέλουµε κάτι τέτοιο. Και κάτι ακόµη. Σύµφωνα µε την

ΑΠ, δεν πρέπει να έχουµε άµεση πρόσβαση στα δεδοµένα ενός αντικειµένου,

αλλά αντ’ αυτού να στέλνουµε ένα µήνυµα, µε το οποίο να ζητάµε την τιµή

του δεδοµένου. Αυτό βέβαια µπορεί να εφαρµοστεί για το κέντρο και την ακτί-

να του κάθε στιγµιότυπου και είναι λογικό. Αντίθετα δεν είναι λογικό να ζητή-

σουµε από ένα στιγµιότυπο να µας ενηµερώσει για τον αριθµό των στιγµιό-

τυπων της κλάσης στην οποία ανήκει. Θα ήταν προτιµότερο να απευθυνθούµε

στην κλάση. Αυτή είναι και η λύση στο πρόβληµα µας. Μια κλάση λοιπόν

µπορεί να έχει µεταβλητές και µεθόδους.

Μια µεταβλητή κλάσης (class variable) ή static µεταβλητή, όπως συνήθως

5 9M ∂ ∆∞ µ § ∏ ∆ ∂ ™ ∫ ∞ π ª ∂ £ √ ¢ √ π ∫ § ∞ ™ ∏ ™

Page 60: Γλώσσες Προγραμματισμού II

6 0 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

αποκαλείται, ανήκει στην κλάση και δεν αποτελεί µέρος της κατάστασης των

στιγµιότυπών της. Μόνο ένα αντίγραφο της κάθε µεταβλητής κλάσης δηµι-

ουργείται. Για τον προσδιορισµό µιας µεταβλητής, σαν µεταβλητής κλάσης

χρησιµοποιούµε τη λέξη κλειδί static.

Αντίστοιχα, µια µέθοδος κλάσης (class method) ή static µέθοδος, ανήκει

στην κλάση δηλαδή προσδιορίζει συµπεριφορά της κλάσης και όχι των στιγ-

µιότυπων της και για το λόγο αυτό είναι ανεξάρτητη από την ύπαρξη ή µή

στιγµιότυπων της κλάσης.

3.4.1 ªÂÙ·‚ÏËÙ¤˜ ÎÏ¿Û˘

Σύµφωνα µε τα παραπάνω, το πρόβληµα της αναπαράστασης του αριθµού

των κύκλων που δηµιουργεί ο χρήστης, είναι µάλλον απλό να αντιµετωπι-

στεί. Το σχήµα 3.8 δίνει τη δήλωση της κλάσης Circle, όπως διαµορφώνεται

µε τα νέα δεδοµένα.:

public class Circle

ssttaattiicc iinntt ccoouunntt == 00;;

public double x,y,r;

public Circle (double x, double y, double r)

this.x=x; this.y=y; this.r=r;

ccoouunntt++++;;

public double circumference ( ) return 2*3.14159*r;

public double area ( ) return 3.14159*r*r;

™¯‹Ì· 3.8

∆ήλωση µεταβλητής

κλάσης.

Παρατηρήστε την αρχικοποίηση της µεταβλητής κλάσης και την ενέργεια

του δηµιουργού να αυξάνει τη µεταβλητή κατά ένα. Φυσικά θα πρέπει να

διασφαλίσουµε, ―θα δούµε το πώς αργότερα― ο απαριθµητής των κύκλων

να µειώνεται µε κάθε αντίστοιχη καταστροφή στιγµιότυπου, για παράδειγ-

µα µε διαγραφή κύκλου από την οθόνη.

Σύµφωνα µε την παραπάνω δήλωση, κάθε στιγµιότυπο της κλάσης (κάθε

Page 61: Γλώσσες Προγραμματισμού II

κύκλος) έχει το δικό του κέντρο και ακτίνα και άρα τις δικές του µεταβλη-

τές x, y και r και επιπλέον υπάρχει ένα µόνο αντίγραφο της µεταβλητής

count ανεξάρτητα από τον αριθµό των στιγµιότυπων της κλάσης που δηµι-

ουργούνται. Το αντίγραφο αυτό υπάρχει και µπορεί να χρησιµοποιηθεί ακόµα

και αν η κλάση δε δηµιουργήσει κανένα στιγµιότυπο. Η αναφορά στη µετα-

βλητή κλάσης από άλλη κλάση γίνεται (µόνο σε περίπτωση βέβαια που έχει

αυτή δηλωθεί public[3]) µε το όνοµα της κλάσης, όπως στην παρακάτω πρό-

ταση για την εκτύπωση του αριθµού των κύκλων, από την κλάση που ανα-

παριστά το πρόγραµµα:

System.out.println("∞ÚÈıÌfi˜ ·ÎψÓ: "+ Circle.count);

Θα παρατηρήσατε βέβαια ότι στον ορισµό του δηµιουργού στο σχήµα 3.8, ανα-

φερθήκαµε στη µεταβλητή κλάσης µόνο µε το όνοµα count, χωρίς το όνοµα

της κλάσης. Αυτό επιτρέπεται µόνο στο σώµα των µεθόδων της κλάσης.

6 1M ∂ ∆∞ µ § ∏ ∆ ∂ ™ ∫ ∞ π ª ∂ £ √ ¢ √ π ∫ § ∞ ™ ∏ ™

[3] Aν έχει δηλωθεί private, πρέπει να ορίσω µια µέθοδο κλάσης που να επιτρέπει

πρόσβαση στη µεταβλητή.

∫·Ù·ÛÙÚÔÊ‹ ∞ÓÙÈÎÂÈ̤ÓÔ˘

Τώρα που γνωρίζετε πώς µπορείτε να δηµιουργήσετε και να χρησιµοποιή-

σετε αντικείµενα, η επόµενη προφανής ερώτηση σας θα είναι: «Πώς κατα-

στρέφουµε αντικείµενα, όταν δεν τα χρειαζόµαστε πια;». Αναµφισβήτητα

πρέπει αυτά να καταστραφούν ώστε να ελευθερώσουν τους πόρους του

συστήµατός σας που είναι περιορισµένοι. Το καλό νέο είναι ότι για την Java

δεν χρειάζεται να ασχοληθείς µε την καταστροφή των αντικειµένων κάτι

που πρέπει να κάνεις στην C++ µε τον τελεστή delete ή ανάλογα στην C

για επιστροφή µνήµης στο σύστηµα, µε τη συνάρτηση της βασικής βιβλιο-

θήκης free(). Το σύστηµα της Java διαθέτει ένα µηχανισµό που είναι

γνωστός σαν συλλογέας σκουπιδιών (garbage collector) και ασχολείται µε

τη συλλογή των άχρηστων αντικειµένων. Αλλά γι’ αυτόν θα πούµε περισ-

σότερα σ’ ένα από τα επόµενα κεφάλαια. Προς το παρόν, µπορείτε να γρά-

φετε τα προγράµµατα σας χωρίς να ανησυχείτε για την καταστροφή των

αντικειµένων σας. Φροντίζει η Java για αυτό.

Page 62: Γλώσσες Προγραμματισμού II

6 2 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

∆εν υπάρχουν γενικές µεταβλητές;

Η Java δεν επιτρέπει γενικές (global) µεταβλητές. Κάθε µεταβλητή στην Java

πρέπει να δηλωθεί µέσα σε µια κλάση. Η Java χρησιµοποιεί τη δεσµευµένη

λέξη static για να δείξει ότι µία συγκεκριµένη µεταβλητή είναι µεταβλητή

κλάσης και όχι µεταβλητή στιγµιότυπου.

Αν εξετάσουµε πιο προσεκτικά το θέµα θα διαπιστώσουµε ότι ναι µεν δεν

επιτρέπει τη δήλωση µιας µεταβλητής έξω από το σώµα µιας κλάσης, αλλά

οι µεταβλητές κλάσης, αν δηλωθούν public, στην ουσία έχουν τα χαρα-

κτηριστικά των γενικών µεταβλητών, µε ένα πρόσθετο πλεονέκτηµα, αυτό

της µηδενικής πιθανότητας σύγκρουσης ονοµάτων. Έτσι, µπορεί να χρησι-

µοποιηθεί η λέξη count για τον ίδιο σκοπό και από άλλες κλάσεις, χωρίς να

δηµιουργείται πρόβληµα σύγκρουσης ονοµάτων.

3.4.2 ™Ù·ıÂÚ‹ ∫Ï¿Û˘

Στο σχήµα 3.4 χρησιµοποιήσαµε τη σταθερή 3.1416 για τον υπολογισµό της

επιφάνειας και της περιµέτρου του κύκλου. Αυτό όπως αντιλαµβάνεστε δηµι-

ουργεί πλεονασµό (redundancy) τον οποίο για να αποφύγουµε στη C χρησι-

µοποιήσαµε είτε τη δήλωση #define του προεπεξεργαστή είτε τη δήλωση

µιας µεταβλητής που δεν αλλάζει τιµή (θυµόσαστε υποθέτω τη λέξη κλειδί

const). H Java δε διαθέτει προεπεξεργαστή και άρα η µόνη λύση είναι η µετα-

βλητή κλάσης που δεν αλλάζει τιµή ή σταθερή κλάσης, όπως αλλιώς την

αποκαλούµε. Για τη δήλωσή της, χρησιµοποιούµε τις λέξεις κλειδιά static

και final, όπως φαίνεται στο σχήµα 3.9. Το static την προσδιορίζει σαν

µεταβλητή κλάσης (ύπαρξη ενός µόνο αντιγράφου), το δε final την προσ-

διορίζει σαν σταθερή, που σηµαίνει ότι η τιµή της δεν µπορεί να αλλάξει

ποτέ. Ο µεταγλωττιστής αναγνωρίζει ως λάθος κάθε πρόταση ανάθεσης τιµής

σε σταθερή όπως π.χ. την Circle.PI=3;

public class Circle

public double x, y, z:

public static final double PI = 3.1415926535; //instance variables

Xρήση κεφαλαίων όπως στη C

ο προορισµός final απαγορεύει εκφράσεις της µορφής

Circle.PI = 2;™¯‹Ì· 3.9

∆ήλωση σταθερής κλάσης.

Page 63: Γλώσσες Προγραμματισμού II

3.4.3 ª¤ıÔ‰ÔÈ ÎÏ¿Û˘

Αντίστοιχα µε τις µεταβλητές κλάσης, οι µέθοδοι κλάσης αναφέρονται στο

µεν εσωτερικό της κλάσης µόνο µε το όνοµά τους,στο δε εξωτερικό µε τη

µορφή

<όνοµα κλάσης>.<όνοµα µεθόδου>

Μια µέθοδος κλάσης µπορεί να κληθεί ανεξάρτητα από την ύπαρξη στιγ-

µιότυπων της κλάσης και είναι σαφές ότι δεν µπορεί να αναφέρεται σε µετα-

βλητές στιγµιότυπων ούτε να χρησιµοποιεί το this. Αντίθετα µπορεί, και

συνήθως χρησιµοποιεί µεταβλητές κλάσης.

Ας θεωρήσουµε τη διεργασία σύγκρισης δύο κύκλων. Έχουµε τη δυνατότη-

τα να αναπαραστήσουµε τη διεργασία

α) σαν µέθοδο στιγµιότυπου και β) σαν µέθοδο κλάσης.

1η επιλογή: Η σύγκριση σαν µέθοδος στιγµιότυπου

Σύµφωνα µε την επιλογή αυτή θεωρούµε ότι το αντικείµενο έχει τη γνώση

που απαιτείται για να συγκρίνει τον εαυτό του µ’ ένα άλλο στιγµιότυπο. Αυτό

υλοποιείται δηλώνοντας τη µέθοδο bigger όπως παρακάτω:

public class Circle

public double x,y,r;

ppuubblliicc CCiirrccllee bbiiggggeerr((CCiirrccllee cc))

if(c.r>r) returnc;else return this;

:

Κάθε στιγµιότυπο της κλάσης µπορεί να δεχτεί ένα µήνυµα της µορφής

bigger(Circle c), η δε απόκρισή του θα προσδιορίζει αν το στιγµιότυ-

6 3M ∂ ∆∞ µ § ∏ ∆ ∂ ™ ∫ ∞ π ª ∂ £ √ ¢ √ π ∫ § ∞ ™ ∏ ™

Να αναπτυχθεί πρόγραµµα το οποίο να δηµιουργεί δύο κύκλους µε κέντρα

(2.0, 2.0) και (5.0, 2.0) και ακτίνες 3.0 και 2.0 αντίστοιχα και στη συνέχεια

να τυπώνει τις επιφάνειες και περιµέτρους τους καθώς και τον αριθµό των

στιγµιοτύπων. Να χρησιµοποιηθεί η έννοια της σταθερής και να ορισθεί ο

κατάλληλος δηµιουργός.

ÕÛÎËÛËA˘ÙÔ·ÍÈÔÏfiÁËÛ˘3.3

Page 64: Γλώσσες Προγραμματισμού II

6 4 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

πο c του ορίσµατος είναι µεγαλύτερο ή όχι απ’ αυτό. Το παρακάτω τµήµα

κώδικα χρησιµοποιεί την µέθοδο bigger.

Circle a = new Circle(2.0);//‰ËÏÒÓÂÈ ÙÔ fiÓÔÌ· a Î·È ÙÔ ‚¿˙ÂÈ

//Ó· ‰Â›¯ÓÂÈ ÛÙÔÓ Î‡ÎÏÔ ·ÎÙ›Ó·˜ 2 Ô˘ ÌfiÏȘ ‰ËÌÈÔ‡ÚÁËÛÂ

Circle b = new Circle(5.0); //‰ËÏÒÓÂÈ ÙÔ fiÓÔÌ· a Î·È ÙÔ ‚¿˙ÂÈ

//Ó· ‰Â›¯ÓÂÈ ÛÙÔÓ Î‡ÎÏÔ ·ÎÙ›Ó·˜ 3 Ô˘ ÌfiÏȘ ‰ËÌÈÔ‡ÚÁËÛÂ

Circle c = a.bigger(b); //‰ËÏÒÓÂÈ ÙÔ fiÓÔÌ· c Î·È ÙÔ

//‚¿˙ÂÈ Ó· ‰Â›¯ÓÂÈ ÛÙÔÓ ÌÂÁ·Ï‡ÙÂÚÔ Î‡ÎÏÔ ·fi ÙÔ˘˜ a Î·È b

H τελευταία πρόταση προσδιορίζει το µεγαλύτερο κύκλο στέλνοντας µήνυ-

µα στο στιγµιότυπο a. Θα µπορούσε να έχει και την µορφή Circle =

b.bigger(a). Μετά την εκτέλεση του παραπάνω κώδικα τα ονόµατα b και

c αναφέρονται στο ίδιο στιγµιότυπο που έχει ακτίνα 5.0.

2η επιλογή: Η σύγκριση σαν µέθοδος κλάσης

Σύµφωνα µε την επιλογή αυτή θεωρούµε ότι η κλάση, και όχι το στιγµιότυ-

πο, έχει τη γνώση που απαιτείται για να συγκρίνει δύο στιγµιότυπά της. Αυτό

υλοποιείται δηλώνοντας τη µέθοδο κλάσης Bigger να δέχεται σαν ορίσµα-

τα δύο στιγµιότυπα κύκλου, όπως δίνεται στο σχήµα 3.10.

public class Circle

public double x,y,r;

ppuubblliicc ssttaattiicc CCiirrccllee BBiiggggeerr((CCiirrccllee aa,, CCiirrccllee bb))

return(a.r>b.r?a:b);

:

™¯‹Ì· 3.10

∆ήλωση µεθόδου κλάσης

Η κλάση µπορεί να δεχτεί µήνυµα της µορφής Bigger(Circle a,

Circle b), και η απόκρισή της θα προσδιορίζει το µεγαλύτερο στιγµιότυ-

πο. Το παρακάτω τµήµα κώδικα χρησιµοποιεί την µέθοδο Bigger.

Circle a = new Circle(2.0

Circle b = new Circle(5.0);

Circle c = Circle.Bigger(a,b); // ‰ËÏÒÓÂÈ ÙÔ fiÓÔÌ· c ηÈ

// ÙÔ ‚¿˙ÂÈ Ó· ‰Â›¯ÓÂÈ ÛÙÔÓ ÌÂÁ·Ï‡ÙÂÚÔ Î‡ÎÏÔ ·fi ÙÔ˘˜ a Î·È b

Page 65: Γλώσσες Προγραμματισμού II

H τελευταία πρόταση στέλνει µήνυµα στην κλάση για να συγκρίνει αυτή τα

δύο στιγµιότυπα. Μετά την εκτέλεση του παραπάνω κώδικα τα ονόµατα b

και c αναφέρονται στο ίδιο στιγµιότυπο κύκλου που έχει ακτίνα 5.0.

Ο πηγαίος κώδικας του σχήµατος 3.11 χρησιµοποιεί µία µέθοδο για να δια-

πιστώσει αν ένα σηµείο βρίσκεται µέσα σ’ έναν ορισµένο κύκλο. Μια τέτοια

µέθοδος δηλώνεται σαν µέθοδος στιγµιότυπου, γιατί αναπαριστά γνώση που

µπορεί και πρέπει να έχει ένα στιγµιότυπο. Εξάλλου η µέθοδος δεν έχει

νόηµα να κληθεί χωρίς να υπάρχει στιγµιότυπο.

6 5M ∂ ∆∞ µ § ∏ ∆ ∂ ™ ∫ ∞ π ª ∂ £ √ ¢ √ π ∫ § ∞ ™ ∏ ™

public class Circle

double x, y, r;

public boolean isInside (double a, double b) // ‚Ú›ÛÎÂÙ·È ÙÔ ÛËÌ›Ô

// (a,b) ̤۷ ÛÙÔÓ Î‡ÎÏÔ;

double dx= a – x;

double dy = b – y;

double distance = Math.sqrt(dx*dx+dy*dy);

return((distance < r) ? true: false);

: // ÏÔȤ˜ ‰ËÏÒÛÂȘ

™¯‹Ì· 3.11

∆ήλωση και χρήση

µεθόδου κλάσης

Είναι ενδιαφέρουσα η έκφραση υπολογισµού της απόστασης από το κέντρο

του κύκλου. Όπως βλέπετε, χρησιµοποιείται η µέθοδος κλάσης sqrt της

κλάσης Math. Μπορείτε να ανατρέξετε στη δήλωση της Math για να δείτε

τον ορισµό της µεθόδου sqrt.

Ανατρέξτε στη ∆ραστηριότητα 3.5. Η µέθοδος addpoint θα µπορούσε κάλ-

λιστα να θεωρηθεί σαν δηµιουργός σηµείου το οποίο θα αποτελεί το άθροι-

σµα δύο άλλων σηµείων. Τροποποιήστε το πρόγραµµα που δηµιουργήσα-

τε στη ∆ραστηριότητα 3.5 ορίζοντας το νέο δηµιουργό. Στη συνέχεια δηµι-

ουργήστε ένα σηµείο σαν άθροισµα των p1(1, 2) και p2(4, 3) και εµφανί-

στε τις συντεταγµένες του στην κύρια έξοδο.

ÕÛÎËÛËA˘ÙÔ·ÍÈÔÏfiÁËÛ˘3.4

Page 66: Γλώσσες Προγραμματισμού II

6 6 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

™‡ÓÔ„Ë

Στο κεφάλαιο αυτό, αναφερθήκαµε στις έννοιες της κλάσης και του αντικει-

µένου και στον τρόπο µε τον οποίο αυτές χρησιµοποιούνται για την ανάπτυ-

ξη προγραµµάτων βασισµένων στην αντικειµενοστρεφή προσέγγιση. Η κλάση

είναι ο µηχανισµός µε τον οποίο οι γλώσσες αντικειµενοστρεφούς προγραµ-

µατισµού υλοποιούν τους αφηρηµένους τύπους δεδοµένων που εµπλέκονται

στην ανάπτυξη κάθε σύνθετου συστήµατος λογισµικού. Μια κλάση είναι η

περιγραφή ενός συνόλου αντικειµένων, τα οποία έχουν κοινά δεδοµένα και

κοινή συµπεριφορά. Αποτελείται, αφενός από τον ορισµό των µεταβλητών

που αναπαριστούν τα δεδοµένα των αντικειµένων, αφετέρου από τον ορισµό

των λειτουργιών που ενεργούν πάνω σ’ αυτά τα δεδοµένα και προσδιορίζουν

τη συµπεριφορά των αντικειµένων στα µηνύµατα που αυτά δέχονται από το

περιβάλλον τους.

Λειτουργία πρωταρχικής σηµασίας για κάθε κλάση είναι η δηµιουργία στιγ-

µιότυπου. Η λειτουργία αυτή εκτελείται σαν αντίδραση της κλάσης στο µήνυ-

µα new το οποίο αποστέλλουµε σε µια κλάση κάθε φορά που θέλουµε να

Θεωρήστε την πρόταση System.out.println(«HelloWorld). Προσπαθήστε

να αντιστοιχίσετε τις έννοιες της πρώτης στήλης µε αυτές της δεύτερης.

System πακέτο

κλάση

out µεταβλητή κλάσης

µεταβλητή στιγµιότυπου

println µέθοδος κλάσης

µέθοδος στιγµιότυπου

ÕÛÎËÛËA˘ÙÔ·ÍÈÔÏfiÁËÛ˘

3.5

Γράψτε ένα πρόγραµµα Java που θα ελέγχει και αναφέρει σε ποιο ή ποια

από τα ορθογώνια rect1((10,20),(50,60)), και rect2((30,40),(80,80)) περιέ-

χεται καθένα από τα παρακάτω σηµεία: p1(60,60), p2(20,30), p3(20,70)

και p4(40,50). Χρησιµοποιήστε σαν υποδοµή τη δουλειά που κάνατε στη

∆ραστηριότητα 5. Μια δική µας έκδοση και τα ανάλογα σχόλια θα βρείτε

στο τέλος του κεφαλαίου.

¢Ú·ÛÙËÚÈfiÙËÙ·3.6

Page 67: Γλώσσες Προγραμματισμού II

δηµιουργήσουµε ένα στιγµιότυπο. Οι δηµιουργοί (constructors), όπως ονο-

µάζονται οι µέθοδοι δηµιουργίας στιγµιότυπων, αποτελούν χαρακτηριστική

περίπτωση µεθόδων κλάσης, µεθόδων δηλαδή που προσδιορίζουν συµπερι-

φορά κλάσης και όχι στιγµιότυπων. Οι µέθοδοι κλάσης έχουν πρόσβαση µόνο

σε µεταβλητές κλάσης (class ή static variables) και όχι στις µεταβλητές στιγ-

µιότυπου, αφού η κλήση τους είναι ανεξάρτητη της ύπαρξης ή µη στιγµιότυ-

που. Για κάθε µεταβλητή κλάσης δηµιουργείται ένα µόνο αντίγραφο, σε αντί-

θεση µε τις µεταβλητές στιγµιότυπου (instance variables) για τις οποίες έχου-

µε ένα αντίγραφο ανά στιγµιότυπο. Μέθοδοι και µεταβλητές κλάσης χρησι-

µοποιούνται από γλώσσες που δεν υποστηρίζουν την κατασκευή της µετα-

κλάσης (metaclass), στην οποία θα αναφερθούµε σε επόµενο κεφάλαιο. Στον

ορισµό µεθόδων κλάσεων και στιγµιότυπου εκµεταλλευόµαστε τη δυνατότη-

τα ορισµού πολλών µεθόδων για µια λειτουργία. Σύµφωνα µε την τεχνική

αυτή που ονοµάζεται υπερφόρτωση µεθόδων, όλες οι µέθοδοι έχουν το ίδιο

όνοµα, αλλά διαφέρουν ως προς τον αριθµό, τον τύπο και τη σειρά των παρα-

µέτρων και τον τύπο της επιστρεφόµενης τιµής.

Για να εξοικειωθούµε στην πράξη µε τις βασικές αυτές έννοιες, χρησιµοποι-

ήσαµε τη γλώσσα προγραµµατισµού Java για την ανάπτυξη των πρώτων µας

αντικειµενοστρεφών προγραµµάτων. Θεωρήσαµε το πρόγραµµά µας σαν ένα

αντικείµενο το οποίο αλληλεπιδρά µε το περιβάλλον του. Η αλληλεπίδραση,

στη φάση αυτή, ήταν απλή και στηρίχθηκε µόνο στο µήνυµα «run» το οποίο

αποστέλλουµε στο πρόγραµµα διαµέσου του λειτουργικού συστήµατος. Την

απόκριση του προγράµµατος µας στο µήνυµα αυτό προσδιορίσαµε µε την

public µέθοδο main, η οποία ορίζει τον τρόπο της αλληλεπίδρασης των αντι-

κειµένων, κλάσεων και στιγµιότυπων, από τα οποία αποτελείται το πρό-

γραµµά µας, κατά τη διάρκεια της εκτέλεσής του. Η αλληλεπίδραση των αντι-

κειµένων υλοποιείται µε την ανταλλαγή µηνυµάτων, η δε αντίδραση τους στα

µηνύµατα που αυτά δέχονται, ορίζεται από τις αντίστοιχες µεθόδους στιγ-

µιότυπου ή κλάσης.

6 7™ Y N O æ H

Page 68: Γλώσσες Προγραμματισμού II

6 8 ∫ ∂ º ∞ § ∞ π √ 3 : K § ∞ ™ ∏ ∫ ∞ π A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √

BÈ‚ÏÈÔÁÚ·Ê›·[1] [IEEE 1983]

Richard Thayer, M.Dorfman «Systems and Software Requirements

Engineering» IEEE Computer Society Press Tutorial.

[2] [Kernighan 88]

Η δεύτερη έκδοση του βιβλίου «The C Programming Language» κυκλο-

φόρησε το 1988, καλύπτοντας πλέον την ANSI C. Ελληνική έκδοση σε

µετάφραση από τον Κλειδάριθµο 1990.

[3] [Meyer 88]

Bertrand Meyer «Object–Oriented Software Construction», Prentice Hall

International.

Μια πολύ καλή και σε βάθος αναφορά στην ΑΠ χρησιµοποιώντας την

αντικειµενοστρεφή γλώσσα Eiffel.

[4] [Rumbaugh et al., 91]

J. Rumbaugh, et.al «Object–Oriented Modeling and Design» Prentice

Hall International.

[5] [Winder 98]

Rusel Winder, Graham Roberts, «Developing Java Software», John

Wiley & Sons.

Page 69: Γλώσσες Προγραμματισμού II

H Java Û·Ó Â¤ÎÙ·ÛË Ù˘ C

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να παρουσιάσει εν συντοµία τους τύπους δεδο-

µένων, τους τελεστές και τις προτάσεις ελέγχου ροής της Java. Η Java έχει

υιοθετήσει τα στοιχεία αυτά µε ελάχιστες διαφοροποιήσεις από την C, µε απο-

τέλεσµα να είστε σε θέση πολύ σύντοµα να χρησιµοποιήσετε ένα µεγάλο µέρος

των δυνατοτήτων της γλώσσας.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• περιγράψετε αλλά και να χρησιµοποιήσετε τους τέσσερις (4) πρωτογενείς

τύπους δεδοµένων της Java, για να δηλώσετε τις µεταβλητές των κλάσεων

σας, αλλά και τα ορίσµατα και τις επιστρεφόµενες τιµές των µεθόδων τους,

• χρησιµοποιήσετε τους τελεστές της Java στη σύνταξη εκφράσεων,

• περιγράψετε τη λειτουργία και τον τρόπο χρήσης οκτώ (8) προτάσεων ελέγ-

χου ροής προγράµµατος, τις οποίες θα είστε πλέον σε θέση να χρησιµο-

ποιείτε στην ανάπτυξη εφαρµογών λογισµικού µε χρήση της Java,

• αναφέρετε 10 τουλάχιστο διαφορές της Java από την C.

ŒÓÓÔȘ ÎÏÂȉȿ

4∫ ∂ º ∞ § ∞ π √

• strongly–typed

• τύπος byte

• τύπος boolean

• τύπος αναφοράς

• null

• κλάσεις String και StringBuffer

• τελεστής instanceof

• exception handling

• multi–threading

• native µέθοδος

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Μετά την εισαγωγή, που κάναµε στο κεφάλαιο 3, στις βασικές έννοιες που

έχουν σχέση µε τον ορισµό και τη διαχείριση κλάσεων και στιγµιότυπων, είστε

σε θέση να γράψετε τα πρώτα σας αντικειµενοστρεφή προγράµµατα. Για τη

συγγραφή των µεθόδων θα πρέπει να χρησιµοποιήσετε τους βασικούς τύπους

της γλώσσας, τους τελεστές της αλλά και τις προτάσεις για τη διαµόρφωση

Page 70: Γλώσσες Προγραμματισμού II

7 0 ∫ ∂ º ∞ § ∞ π √ 4 : H J AVA ™ ∞ ¡ ∂ ¶ ∂ ∫ ∆∞ ™ ∏ ∆ ∏ ™ C

της ροής. Ένα από τα µεγάλα πλεονεκτήµατα της Java, που διευκολύνει στην

εκµάθησή της, είναι το ότι έχει υιοθετήσει τα περισσότερα στοιχεία της C.

Σε αυτό ακριβώς το στοιχείο, βασίζεται το κεφάλαιο αυτό, που παρά τη µικρή

του έκταση καλύπτει τα θέµατα των τύπων δεδοµένων, των τελεστών και των

προτάσεων ελέγχου ροής. Σε κάθε περίπτωση βέβαια προϋποθέτει τη γνώση

και την εξοικείωση µε τις αντίστοιχες έννοιες της C. Για το λόγο αυτό θα σας

συνιστούσα, πριν προχωρήσετε στη µελέτη του κεφαλαίου να κάνετε µια

σύντοµη αναδροµή στα αντίστοιχα κεφάλαια της ΘΕ3.4. Εναλλακτικά, µπο-

ρείτε να υιοθετήσετε µια παράλληλη µελέτη, όπου για κάθε ενότητα του κεφα-

λαίου θα ανατρέχετε στο αντίστοιχο κεφάλαιο της Θεµατικής Eνότητας

(ΘΕ3.4).

4.1 T‡ÔÈ ‰Â‰Ô̤ӈÓ

Στην Java όλες οι εκφράσεις, οι τιµές και τα αντικείµενα επιβάλλεται να

έχουν έναν τύπο. Λέµε πως η Java είναι µια strongly–typed γλώσσα. Ο µετα-

γλωττιστής Java ελέγχει και επιβάλλει τη σωστή χρήση των τύπων διαµέσου

αυστηρών ελέγχων.

Η Java διαθέτει ένα µικρό σύνολο πρωτογενών τύπων και υποστηρίζει τη

δηµιουργία οποιουδήποτε σύνθετου διαµέσου των µηχανισµών της κλάσης,

του interface και του πίνακα. Σαν πρωτογενείς τύπους η Java υιοθετεί τους

τύπους της C µε τις παρακάτω διαφοροποιήσεις:

• υποστηρίζει επιπλέον τους τύπους byte και boolean,

• καθορίζει αυστηρά το µέγεθος κάθε τύπου,

• δεν υποστηρίζει απρόσηµους αριθµούς,

• δεν υποστηρίζει τον τύπο του δείκτη,

• ορίζει για κάθε τύπο µια τιµή η οποία, στην περίπτωση που ο προγραµ-

µατιστής δεν ορίζει τιµή αρχικοποίησης, αποδίδεται σε κάθε δήλωση µετα-

βλητής του τύπου.

4.1.1 O Ù‡Ô˜ Boolean

O τύπος boolean έχει δύο τιµές: αληθή και ψευδή. Οι µεταβλητές τύπου

boolean δεν µπορούν να χρησιµοποιηθούν σαν ακέραιοι αριθµοί και δεν

µπορούν να µετατραπούν από και προς άλλον τύπο. Η πρόταση

b=(i!=0);

Page 71: Γλώσσες Προγραμματισμού II

δίνει τη δυνατότητα έµµεσης µετατροπής του ακεραίου i σε boolean b, µε

την b να παίρνει τιµή αληθή για κάθε τιµή της i διάφορης του 0. Αντίστοι-

χα η πρόταση

i=(b)?1:0;

δίνει τη δυνατότητα έµµεσης µετατροπής του boolean b σε ακέραιο i, µε την

i να παίρνει τιµή 1 για αληθή τιµή της b και 0 για ψευδή τιµή της b.

4.1.2 ∆‡Ô˜ ‰Â›ÎÙË

Η Java δεν υποστηρίζει τον τύπο του δείκτη αφενός για απλοποίηση της

γλώσσας και εξάλειψη όλων εκείνων των προβληµάτων που πηγάζουν από

τον τύπο αυτό, αφετέρου για να δώσει η γλώσσα τις εγγυήσεις ασφαλείας που

απαιτούν οι σύγχρονες εφαρµογές. Οι δείκτες και η αριθµητική δεικτών θα

µπορούσαν να χρησιµοποιηθούν για να αποφευχθούν οι έλεγχοι της Java κατά

την εκτέλεση, αλλά και για να παρακαµφθούν οι µηχανισµοί ασφάλειας.

Η µη υποστήριξη του τύπου του δείκτη µπορεί να φανεί κατ’ αρχήν σηµα-

ντικός περιορισµός, για έναν προγραµµατιστή C. Στην πορεία όµως σύντοµα

θα διαπιστώσετε πως το αντικειµενοστρεφές στυλ προγραµµατισµού δεν έχει

ανάγκη τους δείκτες, αν εξαιρέσουµε βέβαια τη συγγραφή χαµηλού επιπέδου

κώδικα, όπου η χρήση ειδικών µεθόδων γραµµένων σε C είναι απαραίτητη[1].

4.1.3 ∆‡ÔÈ ·Ó·ÊÔÚ¿˜

Τα αντικείµενα και οι πίνακες στην Java ονοµάζονται και τύποι αναφοράς

(reference types) γιατί η διαχείρισή τους βασίζεται στην έννοια της αναφο-

ράς. Έχουµε ήδη αναφέρει, ότι η διεύθυνση κάθε αντικειµένου ή πίνακα απο-

θηκεύεται σε µια µεταβλητή που την ονοµάζουµε αναφορά, αντίθετα µε τους

πρωτογενείς τύπους, η τιµή των οποίων αποθηκεύεται στη µεταβλητή.

Αντιγραφή αντικειµένου

Από τα παραπάνω είναι προφανές ότι η αντιγραφή των δεδοµένων ενός αντι-

κειµένου σ’ ένα άλλο δεν µπορεί να γίνει µε τον τελεστή ανάθεσης. Για την

αντιγραφή των δεδοµένων του αντικειµένου c1 στο c2 αποστέλλουµε το

µήνυµα clone όπως παρακάτω:

Vector c1 = new Vector;

c2 = c1.clone();

7 1T À ¶ √ π ¢ ∂ ¢ √ ª ∂ ¡ ø ¡

[1] Oι µέθοδοι αυτοί είναι γνωστές σαν native methods. Για µια αναφορά στο πολύ

προχωρηµένο αυτό θέµα µπορείτε να ανατρέξετε στο παράρτηµα Α του [Gosling 96].

Page 72: Γλώσσες Προγραμματισμού II

7 2 ∫ ∂ º ∞ § ∞ π √ 4 : H J AVA ™ ∞ ¡ ∂ ¶ ∂ ∫ ∆∞ ™ ∏ ∆ ∏ ™ C

Η αναφορά c2 δείχνει τώρα σ’ ένα αντικείµενο που είναι ακριβές αντίγρα-

φο (κλώνος) του κύκλου c1. Το µήνυµα αυτό βέβαια µπορούν να δεχτούν

µόνο τα αντικείµενα των οποίων οι κλάσεις υλοποιούν το Cloneable

interface[2].

Έλεγχος ισότητας

Ένα άλλο σηµείο που πρέπει να προσεχθεί είναι η έκφραση c1 == c2. Ο

τελεστής == ελέγχει, αν οι δύο αναφορές δείχνουν στο ίδιο αντικείµενο και

όχι αν τα αντικείµενα στα οποία αναφέρονται οι c1 και c2 περιέχουν τις ίδιες

τιµές. Αν θέλουµε να ελέγξουµε, αν δύο αντικείµενα έχουν ίδιες τιµές, θα πρέ-

πει να ορίσουµε µια µέθοδο που να συγκρίνει τις τιµές τους, κάτι ανάλογο της

µεθόδου bigger που ορίσαµε για την κλάση κύκλος στο κεφάλαιο 3.

Η λέξη κλειδί null

Η λέξη null είναι για την Java δεσµευµένη, αντίθετα µε την C, όπου ήταν

απλά µια σταθερή ίση µε µηδέν. Έτσι δεν µπορεί να θεωρηθεί 0 ούτε να χρη-

σιµοποιηθεί σε εκφράσεις µε τους πρωτογενείς τύπους της γλώσσας. Μια

αναφορά, όταν δεν αναφέρεται σε αντικείµενο ή πίνακα, έχει τιµή null.

[2] Στην κατασκευή του interface θα αναφερθούµε σε επόµενο κεφάλαιο.

∆ώστε την έξοδο του παρακάτω τµήµατος κώδικα, χωρίς να τον εκτελέσε-

τε. Στη συνέχεια γράψτε ένα µικρό πρόγραµµα για να επιβεβαιώσετε τα

αποτελέσµατά σας. Τα σχόλιά µας θα βρείτε στο τέλος του κεφαλαίου.

double y, x = 1.0;

Circle c1,c2 ;

c1= new Circle(2.0,2.0,x) ;

c2 = c1;

y = x;

System.out.println("c2.x:"+ c2.x + " c2.y:"+ c2.y + "

c2.r:"+ c2.r);

c1.r = x = 4.0;

System.out.println("c2.x:"+ c2.x + " c2.y:"+ c2.y + "

c2.r:"+ c2.r);

System.out.println("x:" + x +" y:" + y);

¢Ú·ÛÙËÚÈfiÙËÙ·4.1

Page 73: Γλώσσες Προγραμματισμού II

4.1.4 ∆‡Ô˜ ›Ó·Î·

Οι πίνακες, ο χειρισµός των οποίων γίνεται µε αναφορές, είναι αντικείµενα

που περιέχουν συγκεκριµένο αριθµό αντικειµένων κοινού τύπου. Σε µια

δήλωση πίνακα που έχει τη µορφή

int [ ] x; // ‰ËÌÈÔ˘ÚÁ›· ·Ó·ÊÔÚ¿˜

x = new int [10]; // ‰ËÌÈÔ˘ÚÁ›· ·ÓÙÈÎÂÈ̤ÓÔ˘ ηÈ

·Ó¿ıÂÛË ÙÔ˘ ÛÙËÓ ·Ó·ÊÔÚ¿

ή την πιο συµπαγή

int [ ] x = new int [10];

διακρίνουµε τρία επί µέρους στάδια: δηµιουργία µιας αναφοράς, δηµιουρ-

γία του αντικειµένου του πίνακα και τέλος, την ανάθεση του αντικειµένου

στην αναφορά.

Η πρόσβαση στα στοιχεία πίνακα γίνεται όπως ακριβώς και στη C. Η Java

όµως, διαµέσου της µεταβλητής length, η οποία είναι η µόνη µεταβλητή των

πινάκων στην οποία µπορούµε να έχουµε πρόσβαση, παρέχει ένα πιο αξιό-

πιστο τρόπο αναφοράς στο µέγεθος του πίνακα. Η έκφραση <όνοµα αναφο-

ράς πίνακα>.length δίνει το µέγεθος του πίνακα.. Ενδιαφέρον παρουσιάζει

επίσης το γεγονός, ότι η Java εκτελεί έλεγχο σε κάθε δείκτη στοιχείου πίνα-

κα για να διασφαλίσει, ότι δεν επιχειρείται µια αναφορά εκτός των ορίων του

πίνακα. Καταργεί µε τον τρόπο αυτό µια πηγή δύσκολων στην ανεύρεση

σφαλµάτων.

Πολυδιάστατοι πίνακες

Οι πολυδιάστατοι πίνακες δηλώνονται απλά προσθέτοντας διαστάσεις στη

δήλωση του πίνακα. Έτσι η πρόταση

boolean [] [] [] threeDim = new boolean[2][4][6];

δηλώνει έναν πίνακα boolean τριών διαστάσεων 2 ¥ 4 ¥ 6. Οι δε εκφράσεις

threeDim.length

threeDim[1].lenthg

δίνουν τα µεγέθη της πρώτης και δεύτερης διάστασης αντίστοιχα.

7 3T À ¶ √ π ¢ ∂ ¢ √ ª ∂ ¡ ø ¡

Page 74: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 4 : H J AVA ™ ∞ ¡ ∂ ¶ ∂ ∫ ∆∞ ™ ∏ ∆ ∏ ™ C7 4

Αναπτύξτε ένα πρόγραµµα σε Java που θα δηλώνει την αναφορά x σε πίνα-

κα 10 ακεραίων και θα αναθέτει στο πρώτο στοιχείο την τιµή 0 και στα

υπόλοιπα τιµή που θα προκύπτει από το άθροισµα της τάξης του στοιχεί-

ου και της τιµής του προηγούµενου στοιχείου του πίνακα. Τέλος να τυπώ-

νει τα στοιχεία του πίνακα.

ÕÛÎËÛËA˘ÙÔ·ÍÈÔÏfiÁËÛ˘

4.1

∆ηµιουργήστε 12 στιγµιότυπα τύπου Circle µε κέντρα και ακτίνες τα στοι-

χεία των πινάκων 12 στοιχείων point και radius αντίστοιχα.

ÕÛÎËÛËA˘ÙÔ·ÍÈÔÏfiÁËÛ˘

4.2

4.1.5 ∞ÏÊ·ÚÈıÌËÙÈο

H θεώρηση της C ότι τα αλφαριθµητικά είναι πίνακες χαρακτήρων βασίζε-

ται στον τρόπο υποστήριξης της έννοιας από την γλώσσα χωρίς να ασχολεί-

ται µε την έννοια αυτή καθ’ εαυτή. Η Java δεν ακολουθεί αυτή την προσέγ-

γιση και αναπαριστά τον τύπο του αλφαριθµητικού µε την κλάση String.

Κάθε αλφαριθµητικό είναι στιγµιότυπο της κλάσης String και συµπεριφέ-

ρεται, όπως αυτή ορίζει. H κλάση String παρέχει αλφαριθµητικά µόνο ανά-

γνωσης, δεν επιτρέπει δηλαδή µεταβολές της τιµής των στιγµιότυπών της.

Αν απαιτείται κάτι τέτοιο θα πρέπει να χρησιµοποιήσετε την κλάση

StringBuffer. Έτσι, αν πρέπει να τροποποιήσουµε τα περιεχόµενα ενός

στιγµιότυπου τύπου String, πρέπει να δηµιουργήσουµε ένα στιγµιότυπο

της StringBuffer, και µετά να δηµιουργήσουµε ένα νέο στιγµιότυπο της

String µε το τροποποιηµένο περιεχόµενο του στιγµιότυπου

StringBuffer. Ενδιαφέρον παρουσιάζουν, αφενός η συµπεριφορά του

µεταγλωττιστή που αυτόµατα δηµιουργεί ένα στιγµιότυπο String, όταν συνα-

ντήσει µια σταθερή σε διπλά εισαγωγικά, αφετέρου ο τελεστής + που ανα-

παριστά τη διεργασία της συνένωσης δύο στιγµιότυπών της String. Η

παράθεση των κλάσεων String και StringBuffer δεν αποτελεί τµήµα

του παρόντος βιβλίου. Για κάτι τέτοιο θα πρέπει να ανατρέξετε σ’ ένα από

τα πολλά βιβλία που κυκλοφορούν στο εµπόριο για την Java.

Page 75: Γλώσσες Προγραμματισμού II

4.2 TÂÏÂÛÙ¤˜

Η Java υποστηρίζει σχεδόν όλους τους τελεστές της C µε την ίδια µάλιστα

προτεραιότητα. Όπως και στην C, οι παρενθέσεις χρησιµοποιούνται συχνά

σε εκφράσεις για να τροποποιήσουν τη σειρά εφαρµογής των τελεστών, όπως

στον παρακάτω κώδικα:

while ((v = stream.next()) != null)

processValue(v);

Στην έκφραση του while η χρήση των παρενθέσεων είναι απαραίτητη, γιατί

χωρίς αυτές η έκφραση θα ήταν ισοδύναµη µε την (v = (stream.next() !=

null)) καθώς οι τελεστές ανάθεσης έχουν χαµηλότερη προτεραιότητα από

τους τελεστές ισότητας. Η τελευταία έκφραση έχει βέβαια νόηµα µόνο όταν

το v είναι τύπου boolean.

Η Java, σε αντίθεση µε την C, δε θεωρεί σαν τελεστές το [ ] για την προ-

σπέλαση στοιχείων πίνακα και το. για προσπέλαση των πεδίων δοµής. Επι-

πλέον δεν υποστηρίζει:

• τον τελεστή κόµµα (,) για συνδυασµό δύο εκφράσεων σε µία,

• τους τελεστές δεικτών * and &, σαν αποτέλεσµα του γεγονότος ότι δεν επι-

τρέπει τον άµεσο χειρισµό δεικτών,

• τον τελεστή sizeof.

Αντίθετα υποστηρίζει τους παρακάτω νέους τελεστές:

Τελεστής ++:: Ο τελεστής +, που έχει την ίδια προτεραιότητα όπως ο αριθ-

µητικός τελεστής +, εφαρµόζεται σε αλφαριθµητικές τιµές και τις συνενώ-

νει. Εάν ο ένας τελεστέος είναι αλφαριθµητικός, τότε και ο άλλος µετατρέ-

7 5T ∂ § ∂ ™ ∆ ∂ ™

Αναπτύξτε ένα πρόγραµµα που θα δηµιουργεί ένα στιγµιότυπο String µε

περιεχόµενο την λέξη «Hello». Με βάση το στιγµιότυπο αυτό, κάντε τις

απαραίτητες ενέργειες ώστε να έχετε ένα στιγµιότυπο String µε περιεχό-

µενο «Hello world».Τυπώστε το περιεχόµενο του. Ανατρέξτε στην τεκµη-

ρίωση της βασικής βιβλιοθήκης κλάσεων της Java για να δείτε την τεκµη-

ρίωση της String, αλλά και της StringBuffer, που είναι απαραίτητες

για την ανάπτυξη του προγράµµατός σας. Στο τέλος του βιβλίου θα βρείτε

τα δικά µας σχόλια.

¢Ú·ÛÙËÚÈfiÙËÙ·4.2

Page 76: Γλώσσες Προγραμματισμού II

7 6 ∫ ∂ º ∞ § ∞ π √ 4 : H J AVA ™ ∞ ¡ ∂ ¶ ∂ ∫ ∆∞ ™ ∏ ∆ ∏ ™ C

πεται σε αλφαριθµητικό (δες κώδικα δραστηριότητας 1). Η µετατροπή γίνε-

ται για τους µεν πρωτογενείς τύπους αυτόµατα, για τους δε υπόλοιπους µε

τη χρήση της µεθόδου toString(). Ο τελεστής += λειτουργεί για τις αλφα-

ριθµητικές τιµές, όπως και για τις αριθµητικές.

Τελεστής instanceof: O τελεστής instanceof επιστρέφει αληθής, αν το

αντικείµενο στην αριστερή πλευρά του είναι στιγµιότυπο της κλάσης ή υλο-

ποιεί το interface που καθορίζεται στη δεξιά πλευρά του. ∆ιαφορετικά επι-

στρέφει false. False επιστρέφει και όταν το αντικείµενο στο οποίο εφαρµό-

ζεται είναι null. Ο instanceof τελεστής έχει την ίδια προτεραιότητα όπως

οι τελεστές <,<=και >=.

Ανατρέξτε στη βιβλιογραφία και καταγράψτε τις διαφορές µεταξύ των τελε-

στών & και | µε τους αντίστοιχους && και || της Java. Την άποψή µας θα

βρείτε στο τέλος του βιβλίου.

¢Ú·ÛÙËÚÈfiÙËÙ·4.3

4.3 ¶ÚÔÙ¿ÛÂȘ ÂϤÁ¯Ô˘ ÚÔ‹˜ ÚÔÁÚ¿ÌÌ·ÙÔ˜

Οι προτάσεις ελέγχου ροής της Java είναι παρόµοιες µε αυτές της C. Στη συνέ-

χεια κάνουµε µια σύντοµη αναφορά σ’ αυτές, επισηµαίνοντας τις διαφορές.

4.3.1 ¶ÚÔÙ¿ÛÂȘ if/else, while Î·È do/while

Oι προτάσεις if/else, while και do/while, είναι ακριβώς ίδιες µε αυτές

της C µε µοναδική διαφορά ότι ο τύπος boolean στην Java δεν µπορεί να

µετατραπεί αυτόµατα σε άλλους τύπους. Όπως ήδη επισηµάναµε, στην Java

οι τιµές 0 και null δεν εκλαµβάνονται από το σύστηµα σαν false και το ίδιο

ισχύει για τις µη µηδενικές και µη null, που δεν εκλαµβάνονται σαν true.

Ιδιαίτερη προσοχή χρειάζεται στον τύπο της έκφρασης πάνω στην οποία

βασίζονται οι υπό συνθήκη προτάσεις. Η έκφραση αυτή πρέπει να είναι

τύπου boolean και όχι ακέραιου τύπου ή τύπου αναφοράς. Έτσι ο κώδικας

στο σχήµα 4.1 (α) δεν είναι σωστός για την Java. Θα πρέπει να διαµορφω-

θεί όπως εµφανίζεται στο (β) του ίδιου σχήµατος:

Page 77: Γλώσσες Προγραμματισμού II

4.3.2 H ÚfiÙ·ÛË switch

H πρόταση switch είναι ίδια µε την αντίστοιχη πρόταση της C. Ως τιµές

των case ετικετών µπορούµε να χρησιµοποιήσουµε τους τύπους byte,

char, short, int και long. Ο αντικειµενοστρεφής προγραµµατισµός,

χρησιµοποιεί συνήθως το µηχανισµό του πολυµορφισµού για να εκφράσει

την switch λογική. Η χρήση του πολυµορφισµού οδηγεί σε προγράµµατα

που είναι συνήθως πιο ευανάγνωστα, ευκολότερα στη συντήρηση και ευκο-

λότερα στην επεκτασιµότητα από τα αντίστοιχα που χρησιµοποιούν τη λογι-

κή switch.

4.3.3 ∏ ÚfiÙ·ÛË for

for (init–expr; boolean–expr; incr–expr)

statement

H πρόταση είναι ίδια µε αυτή της C µε τις παρακάτω δύο διαφορές:

1) ∆εν υποστηρίζεται ο τελεστής κόµµα (,), ο οποίος στην C επιτρέπει δύο

ή περισσότερες εκφράσεις να ενωθούν σε µία. Χρησιµοποιεί όµως το σύµ-

βολο κόµµα (,) για να διαχωρίσει δύο ή περισσότερες εκφράσεις όταν αυτές

πρέπει να εµφανιστούν είτε στο τµήµα αρχικοποίησης είτε στο τµήµα ενη-

µέρωσης, όχι όµως και στο τµήµα ελέγχου. Στον κώδικα

int i;

7 7¶ ƒ √ ∆∞ ™ ∂ π ™ ∂ § ∂ ° à √ À ƒ √ ∏ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

int i= 10;

while(i– –) // Ï¿ıÔ˜

Circle c1= new Circle();

if (c1) // Ï¿ıÔ˜

int j;

do

:

while (j) ;// Ï¿ıÔ˜

int i= 10;

while(i– – >0)

Circle c1= new Circle();

if (c1 != null)

int j;

do

:

while (j != null) ;

(α) Λάθος κώδικας (β) Σωστός κώδικας

™¯‹Ì· 4.1

Ιδιαίτερη προσοχή απαι-

τείται στις εκφράσεις των

προτάσεων συνθήκης.

Page 78: Γλώσσες Προγραμματισμού II

7 8 ∫ ∂ º ∞ § ∞ π √ 4 : H J AVA ™ ∞ ¡ ∂ ¶ ∂ ∫ ∆∞ ™ ∏ ∆ ∏ ™ C

String str;

for(i=0,, str = "testing"; (i<10)&&(str.length()>=1); i++,,

str =str.substring(1))

System.out.printin(str);

χρησιµοποιείται το (,) στα τµήµατα αρχικοποίησης και ενηµέρωσης µε το

ίδιο αποτέλεσµα που έχει ο αντίστοιχος τελεστής της C. Οι εκφράσεις που

χωρίζονται µε κόµµα υπολογίζονται από αριστερά προς τα δεξιά.

2) H Java επιτρέπει µέσα στο τµήµα αρχικοποίησης τη δήλωση µεταβλητών,

οι οποίες έχουν εµβέλεια µόνο µέσα στην πρόταση for.:

for(iinntt ii=0; i<arr.length; i++)

System.out.println("a[" + i + "] = " + arr[i]);

Προσοχή όµως στον περιορισµό που θέτει η γλώσσα σύµφωνα µε τον οποίο

στο τµήµα αρχικοποίησης επιτρέπεται, είτε ο ορισµός πολλών εκφράσεων

αρχικοποίησης, είτε η δήλωση και αρχικοποίηση πολλών µεταβλητών. ∆εν

επιτρέπει δηλαδή ανάµειξη δηλώσεων αρχικοποίησης µε άλλες εκφράσεις.

4.3.4 √È ÚÔÙ¿ÛÂȘ break Î·È continue

Οι προτάσεις break και continue έχουν τη ίδια συµπεριφορά όπως και στην

C µε την διαφορά, ότι µπορούν προαιρετικά να ακολουθούνται από µια ετι-

κέτα που προσδιορίζει ένα βρόχο που περικλείει την πρόταση continue ή

οποιαδήποτε πρόταση που περικλείει την break. Η παραλλαγή µε την ετικέ-

τα καταργεί τον περιορισµό της C σύµφωνα µε τον οποίο η επίδραση των

προτάσεων αυτών είναι µόνο πάνω στον πλησιέστερο βρόχο. Η ετικέτα δίνει

τη δυνατότητα να ορίσουµε τις προτάσεις έτσι, ώστε να επιδρούν σε οποιο-

δήποτε περικλείοντα βρόχο. Στον παρακάτω κώδικα η εκτέλεση της πρότα-

σης break test; έχει σαν αποτέλεσµα τη µεταφορά του ελέγχου όχι έξω από

την πρόταση while, η οποία την περικλείει, αλλά έξω από την πρόταση που

έχει σηµατοδοτηθεί από την ετικέτα test δηλαδή την if(i < len/2). Έτσι, τερ-

µατίζεται η εκτέλεση όχι µόνο της while αλλά και της περικλείουσας πρό-

τασης if:

for(int i = 0; i < len ; i++)

tteesstt:: if(i < len/2)

Page 79: Γλώσσες Προγραμματισμού II

while (e1)

if(e2)

break tteesstt; // o ¤ÏÂÁ¯Ô˜ ÌÂٷʤÚÂÙ·È

// ÛÙÔ ÛËÌÂ›Ô Ô˘

// ‰Â›¯ÓÂÈ ÙÔ ‚¤ÏÔ˜

:

:

Σηµειώστε ότι ο έλεγχος δε µεταφέρεται στην πρόταση που προσδιορίζει η

ετικέτα αλλά έξω από την πρόταση αυτή.

4.3.5 ∏ ÚfiÙ·ÛË goto

Η πρόταση goto δεν υποστηρίζεται. Ορισµένες από τις περιπτώσεις χρήσης

της στην C καλύπτονται από τις break και continue µε ετικέτες και άλλες από

την πρόταση try/catch/finally. Για περισσότερα στο θέµα αυτό µπορείτε να

ανατρέξετε στην ενότητα 6.10 του [Gosling 96], όπου αναφέρονται οι βασι-

κές χρήσεις της κατασκευής goto σε γλώσσες που την υποστηρίζουν.

4.4 §ÔȤ˜ ‰È·ÊÔÚ¤˜ Ù˘ Java ·fi ÙËÓ C

Είναι ενδιαφέρον στο σηµείο αυτό να αναφερθούµε και σε ορισµένες ακόµη

διαφορές µεταξύ των δύο γλωσσών, οι οποίες θα σας βοηθήσουν στη γρή-

γορη αξιοποίηση των δυνατοτήτων της Java. Η Java:

• δίνει δυνατότητα δήλωσης τοπικών µεταβλητών σε κάθε µπλοκ κώδικα,

• επιτρέπει υπερφόρτωση µεθόδων,

• δεν υποστηρίζει καθολικές µεταβλητές (τις υποστηρίζει όµως έµµεσα),

• δεν υποστηρίζει τη λέξη κλειδί typedef,

• δεν υποστηρίζει struct, union και bitfields,

• δεν υποστηρίζει τον απαριθµητικό (enum) τύπο,

• δεν διαθέτει µηχανισµό υποστήριξης µεταβλητού αριθµού παραµέτρων

για τις µεθόδους,

7 9§ √ π ¶ ∂ ™ ¢ π ∞ º √ ƒ ∂ ™ ∆ ∏ ™ J AVA ∞ ¶ √ ∆ ∏ ¡ C

Page 80: Γλώσσες Προγραμματισμού II

8 0 ∫ ∂ º ∞ § ∞ π √ 4 : H J AVA ™ ∞ ¡ ∂ ¶ ∂ ∫ ∆∞ ™ ∏ ∆ ∏ ™ C

• αντιµετωπίζει διαφορετικά τα ορίσµατα γραµµής διαταγών,

• δεν χρησιµοποιεί το void σε περίπτωση που µια µέθοδος δεν δέχεται παρα-

µέτρους,

• δεν διαθέτει προ–επεξεργαστή,

• υποστηρίζει διαχείριση εξαιρέσεων (exception handling),

• υποστηρίζει πολλαπλά νήµατα (multiple threads).

Μπορείτε να ανατρέξετε στο τέλος του κεφαλαίου 2 του [Flanagan 96], όπου

γίνεται µια εκτενής αναφορά στις παραπάνω διαφορές της Java από την C.

™‡ÓÔ„Ë

Στο κεφάλαιο αυτό αναφέραµε εν συντοµία τους τύπους δεδοµένων, τους

τελεστές και τις προτάσεις ελέγχου ροής της Java. Στα θέµατα αυτά η Java

υιοθετεί τις αντίστοιχες κατασκευές της C. Πιο συγκεκριµένα, χρησιµοποιεί

µε ελάχιστες τροποποιήσεις όλους τους τύπους δεδοµένων της C, εκτός του

τύπου του δείκτη, εισάγει τους τύπους boolean και byte, και χρησιµοποιεί για

τη διαχείριση των στιγµιότυπων τον τύπο αναφοράς. Σηµαντική διαφορο-

ποίηση υπάρχει στη διαχείριση των αλφαριθµητικών. Η Java δεν αντιµετω-

πίζει τα αλφαριθµητικά σαν πίνακες χαρακτήρων, αλλά σαν στιγµιότυπα της

κλάσης String, η γνώση της οποίας αποτελεί βασική προϋπόθεση για τη δια-

χείριση των αλφαριθµητικών.

Όσον αφορά τους τελεστές, η Java υποστηρίζει σχεδόν όλους τους τελεστές

της C, µε την προτεραιότητα µάλιστα που αυτοί έχουν και στην C. Στις ελά-

χιστες διαφοροποιήσεις περιλαµβάνονται: η µη υποστήριξη των τελεστών

άµεσης διεύθυνσης (&), περιεχοµένου (*), κόµµα (,) και sizeof, η επέκταση

της χρήσης του τελεστή +, ώστε να δρα και σε αλφαριθµητικά, η εισαγωγή

του τελεστή instanceof και η ύπαρξη ξεχωριστών τελεστών AND και OR για

υπολογισµούς περιορισµένης έκτασης.

Στο θέµα της διαχείρισης της ροής η Java παρουσιάζεται πολύ ισχυρή. Κατ’

αρχήν, υιοθετεί όλες τις αντίστοιχες προτάσεις της C µε εξαίρεση την πρότα-

ση goto, ενώ ταυτόχρονα ενισχύει την εµβέλεια των break και continue σε

περισσότερους βρόχους. Η σηµαντική διαφοροποίηση όµως, που την καθι-

στά περισσότερο ευέλικτη και αποτελεσµατική, είναι αφενός η ύπαρξη µηχα-

νισµού χειρισµού εξαιρέσεων, αφετέρου η διαχείριση πολλών ταυτόχρονων

ροών ελέγχου, νηµάτων (threads) όπως τα ονοµάζουµε.

Page 81: Γλώσσες Προγραμματισμού II

BÈ‚ÏÈÔÁÚ·Ê›·

[1] [Flanagan 96]

David Flanagan, «Java in a Nutshell», O’Reilly and Associates Inc.,

1996.

Το βιβλίο καλύπτει στο πρώτο µέρος τα βασικά στοιχεία της γλώσσας

και αφιερώνει το δεύτερο και µεγαλύτερο στο API της Java µε πολλά

παραδείγµατα στον τρόπο χρήσης των εξυπηρετήσεών του. Αποτελεί

κατά τη γνώµη µου ένα από τα καλύτερα βιβλία για τη Java.

[2] [Gosling 96]

Ken Arnold, James Gosling, «The Java Programming Language»,

Addison Wesley, 1996.

Το βιβλίο αποτελεί µια πολύ καλή και σχετικά σύντοµη αναφορά στη

γλώσσα καλύπτοντας τα βασικά στοιχεία και αποφεύγοντας κουραστι-

κές πολυλογίες. Στα θετικά του είναι ότι ο ένας εκ των δύο των συγ-

γραφέων του, ο James Gosling θεωρείται ο πρωτεργάτης της οµάδας

ανάπτυξης της γλώσσας στα εργαστήρια της Sun.

8 1B I B § I O ° PA º I A

Page 82: Γλώσσες Προγραμματισμού II
Page 83: Γλώσσες Προγραμματισμού II

H KÏ¿ÛË Û·Ó ¢ÔÌÈÎfi ™ÙÔÈ¯Â›Ô ÙÔ˘ ¶ÚÔÁÚ¿ÌÌ·ÙÔ˜

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να εξετάσει τα διάφορα είδη συσχετίσεων που

υπάρχουν µεταξύ των κλάσεων αλλά και να περιγράψει τους µηχανισµούς

προσδιορισµού της ορατότητας των κατασκευών του αντικειµενοστρεφούς

προγραµµατισµού.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• αναφέρετε 6 τουλάχιστο µορφές συσχετίσεων µεταξύ κλάσεων,

• περιγράψετε κάθε µία από τις διάφορες µορφές συσχετίσεων µεταξύ κλά-

σεων και να αναφέρετε τις δύο σηµαντικότερες από αυτές,

• δώσετε τον ορισµό της µετα–κλάσης,

• περιγράψετε πως η Java και η C++ αναπληρώνουν εν µέρει την κατα-

σκευή της µετα–κλάσης την οποία δεν υποστηρίζουν,

• αναφέρετε τους προσδιοριστές ορατότητας της Java,

• περιγράψετε την επίδραση καθενός από τους παραπάνω προσδιοριστές,

τους οποίους θα είστε πλέον σε θέση να χρησιµοποιείτε κατάλληλα στις

δηλώσεις σας,

• αναφέρετε τις 5 περιοχές εµβέλειας που διακρίνει η Java,

• αναφέρετε αιτίες για τον ορισµό ένθετων κλάσεων.

ŒÓÓÔȘ–KÏÂȉȿ

5∫ ∂ º ∞ § ∞ π √

• link

• aggregation

• association

• inheritance

• using

• instantiation

• metaclass

• συµπερίληψη µε τιµή

• συµπερίληψη µε αναφορά

• actor

• server

• agent

• public

• private

Page 84: Γλώσσες Προγραμματισμού II

8 4 ∫ ∂ º ∞ § ∞ π √ 5 : H K § ∞ ™ ∏ ™ ∞ ¡ ¢ √ ª π ∫ √ ™ ∆ √ π à ∂ π √ ∆ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Στο κεφάλαιο 3 περιγράψαµε τις έννοιες της κλάσης και του στιγµιότυπου και

αναφέραµε πως ένα πρόγραµµα στο χρόνο µεταγλώττισης αποτελείται από ένα

σύνολο από δηλώσεις κλάσεων. Οι κλάσεις αυτές, αφού ανήκουν στο ίδιο πρό-

γραµµα, είναι λογικό να έχουν σχέσεις µεταξύ τους. Ήδη, από την εισαγωγή ανα-

φέραµε ορισµένες µορφές σχέσεων που παρατηρούνται µεταξύ των βασικών

εννοιών του προβλήµατος. Οι σχέσεις αυτές θα πρέπει τώρα να αναπαραστα-

θούν σαν συσχετίσεις µεταξύ των κλάσεων που αναπαριστούν τις έννοιες του

προβλήµατος (problem space classes). Επιπλέον, στην προσπάθεια επίλυσης

του προβλήµατος, νέες κλάσεις δηλώνονται (solution space classes) αυξάνο-

ντας τον αριθµό των κλάσεων, αλλά και των συσχετίσεων, και δηµιουργώντας

την ανάγκη µηχανισµών οργάνωσης και ελέγχου της ορατότητάς τους.

Στο κεφάλαιο αυτό, που είναι οργανωµένο σε τρεις ενότητες, εξετάζουµε τις

διάφορες κατηγορίες συσχετίσεων µεταξύ των κλάσεων καθώς και τους προσ-

διοριστές της ορατότητας των κατασκευών µιας αντικειµενοστρεφούς γλώσ-

σας, που διευκολύνουν την οργάνωση του πηγαίου κώδικα των προγραµµά-

των. Πιο συγκεκριµένα, στην πρώτη ενότητα εξετάζουµε τις δύο βασικές κατη-

γορίες σχέσεων µεταξύ αντικειµένων, αλλά και τους ρόλους που ένα αντι-

κείµενο µπορεί να διαδραµατίζει µέσα σ’ ένα πρόγραµµα. Στη συνέχεια

κάνουµε µια σύντοµη αναφορά στις κατηγορίες των συσχετίσεων µεταξύ των

κλάσεων και του τρόπου αντιµετώπισής τους από τις αντικειµενοστρεφείς

γλώσσες. Στη δεύτερη ενότητα, καταγράφονται οι προσδιοριστές ορατότητας

των συνθετικών µιας κλάσης προς τις δύο κατηγορίες πελατών της, τα στιγ-

µιότυπά της αλλά και τις κλάσεις απογόνους της. Τέλος, στην τρίτη ενότητα

επεκτείνεται η έννοια της ορατότητας σε επίπεδο κλάσης και περιγράφεται,

πώς η θέση δήλωσης µιας κλάσης επηρεάζει την εµβέλεια της.

Θα σας συνιστούσα να δώσετε ιδιαίτερη έµφαση στις ενότητες 5.2 και 5.3,

καθώς έχουν άµεση εφαρµογή στην οργάνωση ενός αντικειµενοστρεφούς προ-

γράµµατος. Στην ενότητα 5.1 µπορείτε να επανέλθετε και µετά την ολοκλή-

ρωση και του κεφαλαίου 8 οπότε και θα έχετε ένα καλύτερο υπόβαθρο για

την σε βάθος κατανόηση των εννοιών του, κάτι που οπωσδήποτε θα απαιτή-

• protected

• εµβέλεια

• ένθετη κλάση

• κλάση µέλους

• τοπική κλάση

• ανώνυµη κλάση

Page 85: Γλώσσες Προγραμματισμού II

σει και αναφορά στη βιβλιογραφία.

Πριν προχωρήσετε στη µελέτη του κεφαλαίου, δώστε λίγο χρόνο για την εκτέ-

λεση της παρακάτω ∆ραστηριότητας:

8 5O π ∫ § ∞ ™ ∂ π ™ ¢ ∂ ¡ ∂ π ¡ ∞ π ∞ ¡ ∂ • ∞ ƒ ∆ ∏ ∆ ∂ ™ ª ∂ ∆∞ • À ∆ √ À ™

∆ώστε τον ορισµό της κλάσης κύκλος προσδιορίζοντας τη συµπεριφορά

στα µηνύµατα area και circumference αντίστοιχα. Την απάντησή µας θα

βρείτε στο τέλος του βιβλίου.

¢Ú·ÛÙËÚÈfiÙËÙ·5.1

5.1 OÈ ÎÏ¿ÛÂȘ ‰ÂÓ Â›Ó·È ·ÓÂÍ¿ÚÙËÙ˜ ÌÂٷ͇ ÙÔ˘˜

5.1.1 ™¯¤ÛÂȘ ·ÓÙÈÎÂÈ̤ӈÓ

Τα αντικείµενα συνεργάζονται µεταξύ τους και συνεισφέρουν το καθένα µε

το δικό του τρόπο στη συνολική συµπεριφορά του συστήµατος. Η συσχέτι-

ση µεταξύ δύο αντικειµένων αφορά τις θεωρήσεις που το καθένα κάνει για

το άλλο, περιλαµβάνοντας κυρίως τις λειτουργίες που µπορούν να εκτελε-

στούν και την αναµενόµενη συµπεριφορά. Οι Seidewitz και Stark διακρίνουν

σαν σηµαντικότερους τύπους συσχετίσεων τις seniority και parent/child

συσχετίσεις. Τις συσχετίσεις αυτές, αναφέρει ο Booch [Booch 94] αντίστοι-

χα σαν Links και Aggregation.

Links

Ο όρος link, προέρχεται από την ΟMT µεθοδολογία, όπου ορίζεται σαν

«φυσική ή ιδεατή σύνδεση µεταξύ των αντικειµένων». Ένα αντικείµενο

συνεργάζεται µε άλλα αντικείµενα διαµέσου των δεσµών του. Ένας δεσµός

προσδιορίζει τη συγκεκριµένη σχέση, διαµέσου της οποίας ένα αντικείµε-

νο–πελάτης (client) χρησιµοποιεί τις εξυπηρετήσεις άλλου αντικειµένου που

ονοµάζεται προµηθευτής (supplier). Κάθε αντικείµενο συµµετέχει σ’ ένα

δεσµό µ’ έναν από τους παρακάτω ρόλους, όπως τους ορίζει ο Booch.

Actor: Ένα αντικείµενο που ενεργεί πάνω σ’ άλλα αντικείµενα, αλλά ποτέ

δεν εξυπηρετεί άλλα αντικείµενα. Πολλές φορές αναφέρεται και σαν active

object.

Server: Tο αντικείµενο που ποτέ δεν ενεργεί σ’ άλλα αντικείµενα, αλλά µόνο

παρέχει εξυπηρετήσεις σ’ άλλα αντικείµενα.

Agent: Tο αντικείµενο που ενεργεί πάνω, αλλά και παρέχει εξυπηρετήσεις,

Page 86: Γλώσσες Προγραμματισμού II

8 6 ∫ ∂ º ∞ § ∞ π √ 5 : H K § ∞ ™ ∏ ™ ∞ ¡ ¢ √ ª π ∫ √ ™ ∆ √ π à ∂ π √ ∆ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

σ’ άλλα αντικείµενα. Ένας agent δηµιουργείται συνήθως για την εκτέλεση

ενός έργου για λογαριασµό ενός actor ή ενός άλλου agent.

Είναι προφανές ότι ένα αντικείµενο µπορεί να αποστείλει µήνυµα σε κάποιο

άλλο, µόνο αν το αντικείµενο παραλήπτης του είναι ορατό µε κάποιο τρόπο.

Έτσι αν θεωρήσουµε τα αντικείµενα Α και Β µ’ ένα δεσµό µεταξύ τους, τότε

για να µπορεί το Α να χρησιµοποιήσει εξυπηρέτηση του Β πρέπει να έχει

πρόσβαση σε αυτό. Η πρόσβαση αυτή µπορεί να έχει µια από τις παρακά-

τω µορφές:

• Tο αντικείµενο–προµηθευτής είναι ορατό στο αντικείµενο πελάτη. Για να

προσδιορίσουµε την ορατότητα των αντικειµένων χρησιµοποιούµε, όπως

θα δούµε στη συνέχεια, τους προσδιοριστές ορατότητας.

• Tο αντικείµενο–προµηθευτής αποτελεί παράµετρο σε κάποια µέθοδο του

αντικειµένου–πελάτη.

• Tο αντικείµενο–προµηθευτής είναι τµήµα του αντικειµένου–πελάτη.

• Tο αντικείµενο–προµηθευτής είναι ένα τοπικά ορισµένο αντικείµενο σε

µια µέθοδο του πελάτη.

Είναι σαφές από τα παραπάνω ότι ο προσδιορισµός της ορατότητας έχει

µεγάλη σηµασία στην οργάνωση του προγράµµατος, κάτι που εξάλλου είχα-

µε δει και στο διαδικαστικό προγραµµατισµό.

Αναπαραστήστε µε κώδικα Java τις παραπάνω περιπτώσεις πρόσβασης αντι-

κειµένου– πελάτη σε αντικείµενο–προµηθευτή. ∆ώστε µόνο το σκελετό.

Ενδιαφέρον παρουσιάζει η ερώτηση «Tι συµβαίνει, όταν ένα αντικείµενο

αποστέλλει ένα µήνυµα σ’ ένα άλλο διαµέσου ενός δεσµού;». Σ’ ένα πλή-

ρως ακολουθιακό περιβάλλον, η αποστολή µηνύµατος συνήθως υλοποιεί-

ται από µια απλή κλήση της αντίστοιχης µεθόδου. Αυτός είναι και ο λόγος

που πολλοί συγγραφείς θεωρούν τον όρο message passing ταυτόσηµο µε

τον όρο method call. Ωστόσο, σ’ ένα πολυ–νηµατικό περιβάλλον, ένα περι-

βάλλον δηλαδή στο οποίο πολλά νήµατα (threads of control) µπορούν να

είναι ενεργά ταυτόχρονα, υπάρχει ανάγκη από πιο σύνθετους µηχανισµούς

διαβίβασης µηνυµάτων. Οι µηχανισµοί αυτοί, όπως θα δούµε αναλυτικά σε

επόµενο κεφάλαιο, επιτρέπουν τη διαχείριση των καταστάσεων που ανα-

κύπτουν σε ταυτόχρονα δρώντα (concurrent) συστήµατα.

ÕÛÎËÛËA˘ÙÔ·ÍÈÔÏfiÁËÛ˘

5.1

Page 87: Γλώσσες Προγραμματισμού II

Aggregation

Ενώ ο δεσµός αποτελεί µια ισότιµη διασύνδεση ή µια διασύνδεση πελάτη

προµηθευτή, η συνάθροιση υποδηλώνει µια ιεραρχία όλου–µέρους, που µας

επιτρέπει να κινηθούµε από το όλο στα µέρη του, τα οποία είναι γνωστά µε

τον όρο κατηγορήµατα. Αντίθετα, η κίνηση από το µέρος στο όλο, είναι

δυνατή µόνο αν αυτή η πληροφορία αποτελεί µέρος της κατάστασης του

συγκεκριµένου κατηγορήµατος.

Η συνάθροιση δε δηλώνει απαραίτητα φυσική συµπερίληψη. ∆ιαφορετική

είναι η σχέση συνάθροισης που συνδέει το αυτοκίνητο µε τα µέρη του απ’ ό,τι

η αντίστοιχη σχέση του προσώπου µε τους τίτλους µετοχών που κατέχει. Στη

δεύτερη αυτή περίπτωση, η σχέση είναι περισσότερο ιδεατή και λιγότερο

άµεση από την αντίστοιχη φυσική συνάθροιση των µερών του αυτοκινήτου.

5.1.2 ™˘Û¯ÂÙ›ÛÂȘ ÌÂٷ͇ ÎÏ¿ÛˆÓ

Αν θεωρήσουµε τις κλάσεις µεταφορικό µέσο, άνθρωπος, αυτοκίνητο, πλοίο,

ιπτάµενο δελφίνι, µηχανή, ναυάγιο και ferryboat, µπορούµε να καταγρά-

ψουµε τα παρακάτω:

• Tο αυτοκίνητο όπως και το πλοίο είναι είδη µεταφορικού µέσου.

• Tο ιπτάµενο δελφίνι και το ferryboat είναι είδη πλοίου.

• O άνθρωπος χρησιµοποιεί το ιπτάµενο δελφίνι.

• H µηχανή είναι µέρος του πλοίου αλλά και του αυτοκινήτου.

• Ένα πλοίο αλλά και ένα αυτοκίνητο µπορεί να έχει σχέση µε ένα ναυάγιο.

Όπως εύκολα διαπιστώνουµε από τα παραπάνω, οι κλάσεις όπως και τα στιγ-

µιότυπα έχουν σχέσεις µεταξύ τους. Οι σχέσεις αυτές ορίζουν τη δοµή κλά-

σεων του συστήµατός µας, µια δοµή που εκφράζεται από το διάγραµµα κλά-

σεων (class diagram), που δηµιουργούµε στη φάση της ανάλυσης και του

σχεδιασµού. Είναι λογικό να αναµένουµε από το περιβάλλον υλοποίησης

κατάλληλους µηχανισµούς για την υλοποίηση αυτών των σχέσεων. Έτσι, οι

περισσότερες αντικειµενοστρεφείς γλώσσες παρέχουν άµεση υποστήριξη για

τις επόµενες κατηγορίες συσχετίσεων:

• Association

• Inheritance

• Aggregation

8 7O π ∫ § ∞ ™ ∂ π ™ ¢ ∂ ¡ ∂ π ¡ ∞ π ∞ ¡ ∂ • ∞ ƒ ∆ ∏ ∆ ∂ ™ ª ∂ ∆∞ • À ∆ √ À ™

Page 88: Γλώσσες Προγραμματισμού II

8 8 ∫ ∂ º ∞ § ∞ π √ 5 : H K § ∞ ™ ∏ ™ ∞ ¡ ¢ √ ª π ∫ √ ™ ∆ √ π à ∂ π √ ∆ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

• Using

• Instantiation

• Metaclass

Από τις συσχετίσεις αυτές η κληρονοµικότητα (inheritance) αποτελεί την

πλέον ισχυρή και ενδιαφέρουσα συσχέτιση. Χρησιµοποιείται για να εκφρά-

σει τη σχέση γενίκευσης /εξειδίκευσης, όπως αυτή που συνδέει την κλάση

πλοίο µε τις κλάσεις ιπτάµενο δελφίνι και ferryboat. Στη συσχέτιση αυτή θα

αναφερθούµε εκτενώς στο κεφάλαιο 6, ενώ στις υπόλοιπες θα κάνουµε µια

σύντοµη αναφορά στη συνέχεια. Για µια πιο αναλυτική αναφορά µπορείτε

να ανατρέξετε στην ενότητα 3.4 του [Booch 94], αφού όµως ολοκληρώσετε

πρώτα το παρόν κεφάλαιο.

Association

Η λιγότερο σηµασιολογικά ισχυρή από τις συσχετίσεις είναι αυτή της

Association, που υποδηλώνει κάποια εξάρτηση µεταξύ των κατά τα άλλα

ανεξάρτητων κλάσεων, όπως για παράδειγµα η συσχέτιση µεταξύ των κλά-

σεων αυτοκίνητο και ναυάγιο. Η συσχέτιση αυτή, που δεν προσδιορίζει τον

ακριβή τρόπο µε τον οποίο η µια κλάση σχετίζεται µε την άλλη, είναι ικα-

νοποιητική για τις πρώτες φάσεις της ανάπτυξης, αλλά στη φάση της υλο-

ποίησης θα πρέπει να αντικατασταθεί από τη σχέση using.

Using

Μια association υποδηλώνει µια αµφίδροµη σηµασιολογική συσχέτιση. Η

using είναι αποτέλεσµα µιας διαδικασίας εκλέπτυνσης (refinement) µιας

association κατά την οποία υποδηλώνουµε ποια κλάση είναι πελάτης και ποια

προµηθευτής συγκεκριµένων εξυπηρετήσεων. H σχέση using αποτελεί την

αναπαράσταση της σχέσης link που καταγράψαµε ανάµεσα στα στιγµιότυπα.

Aggregation

Ιδιαίτερο ενδιαφέρον παρουσιάζει η συσχέτιση της συνάθροισης

(aggregation) που καταγράφει τη σχέση όλου–µέρους που εντοπίζουµε στα

στιγµιότυπα των κλάσεων. ∆ύο κλάσεις συσχετίζονται µεταξύ τους µε σχέση

συνάθροισης µόνο και µόνο όταν υπάρχει µια σχέση όλου–µέρους µεταξύ

των στιγµιότυπών τους ή πιο συγκεκριµένα για τη φάση της υλοποίησης,

όταν η µία κλάση περιλαµβάνει σαν µέλη (members) της, στιγµιότυπα της

άλλης. Η σχέση συνάθροισης µπορεί να αναπαριστά φυσική συµπερίληψη ή

όχι. Στην πρώτη περίπτωση που είναι γνωστή, στη φάση της υλοποίησης,

Page 89: Γλώσσες Προγραμματισμού II

σαν συµπερίληψη µε τιµή (containment by value), το µέρος δεν υπάρχει

ανεξάρτητα από το όλο. Αντίθετα, η διάρκεια ζωής του µέρους είναι άµεσα

εξαρτηµένη από τη διάρκεια ζωής του όλου. Όταν δηµιουργούµε ένα στιγ-

µιότυπο της κλάσης του όλου δηµιουργούµε και ένα ή περισσότερα[1] στιγ-

µιότυπα της κλάσης µέρους.

Στη δεύτερη περίπτωση, που είναι γνωστή σαν συµπερίληψη µε αναφορά

(containment by reference), οι διάρκειες ζωής των δύο στιγµιότυπων δεν

έχουν ισχυρή εξάρτηση µεταξύ τους. Μπορούµε ανεξάρτητα να δηµιουρ-

γούµε και να καταστρέφουµε στιγµιότυπα των δύο κλάσεων. Το aggregate

είναι ένα αντικείµενο, το οποίο, αν και αποτελείται από επί µέρους συνθετι-

κά, αντιµετωπίζεται σαν ένα αντικείµενο όσον αφορά ορισµένες λειτουργίες.

Τα συνθετικά µπορούν να υπάρχουν ή όχι, ανεξάρτητα από το aggregate αντι-

κείµενο ή ακόµη να συµµετέχουν σε περισσότερες συναθροίσεις.

Για µια λεπτοµερή και κατανοητή αναφορά στη συσχέτιση της συνάθροισης

θα σας συνιστούσα µετά την ολοκλήρωση του κεφαλαίου να ανατρέξετε

στην ενότητα 4.1 του [Rumbaugh 91].

Instantiation

Η σχέση instantiation, που χρησιµοποιούν γλώσσες όπως η Ada, C++ και

Eiffel, υποστηρίζει, όπως και η inheritance, µια µορφή γενίκευσης µε τελεί-

ως όµως διαφορετικό τρόπο. Η κατασκευή µε το όνοµα παραµετρική

(parameterized ή generic) κλάση που πρώτα εισήχθη από την CLU χρησι-

µοποιείται σαν πρότυπο (template) για την παραγωγή άλλων κλάσεων. Μια

παραµετρική κλάση δεν µπορεί να έχει στιγµιότυπα παρά µόνο αφού δηµι-

ουργήσουµε µια τουλάχιστο διακριτή (concrete) κλάση της, ορίζοντας τις

παραµέτρους της. Αν και ορισµένοι ερευνητές, όπως ο Meyer, υποστηρίζουν

πως η κληρονοµικότητα είναι πιο ισχυρός µηχανισµός και όλα τα πλεονε-

κτήµατα των παραµετρικών κλάσεων µπορούν να επιτευχθούν µε τη χρήση

του µηχανισµού αυτού, κάτι που δεν ισχύει αντίστροφα, στην πράξη οι γλώσ-

σες που διαθέτουν και τους δύο µηχανισµούς πλεονεκτούν. Χαρακτηριστι-

κό είναι το παράδειγµα της παραµετρικής κλάσης Queue που χρησιµοποιεί

ο Booch στην σελίδα 131 της ενότητα 3.4 του [Booch 94]. Την παραµετρι-

κή κλάση Queue χρησιµοποιεί στη συνέχεια για να ορίσει τις διακριτές κλά-

σεις intQueue και itemQueue, στιγµιότυπα των οποίων χρησιµοποιεί για απο-

θήκευση και ανάκληση ακέραιων και στιγµιότυπων της κλάσης item αντί-

8 9O π ∫ § ∞ ™ ∂ π ™ ¢ ∂ ¡ ∂ π ¡ ∞ π ∞ ¡ ∂ • ∞ ƒ ∆ ∏ ∆ ∂ ™ ª ∂ ∆∞ • À ∆ √ À ™

[1] Eξαρτάται από την πολλαπλότητα (cardinality) της συσχέτισης.

Page 90: Γλώσσες Προγραμματισμού II

9 0 ∫ ∂ º ∞ § ∞ π √ 5 : H K § ∞ ™ ∏ ™ ∞ ¡ ¢ √ ª π ∫ √ ™ ∆ √ π à ∂ π √ ∆ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

στοιχα, διατηρώντας ταυτόχρονα το πλεονέκτηµα της ασφάλειας τύπων

(type–safe).

Metaclass Association

Οι συσχετίσεις του τύπου metaclass είναι τελείως διαφορετικές και υποστη-

ρίζονται από γλώσσες όπως οι Smalltalk, CLOS και Objective–C, που υπο-

στηρίζουν την έννοια της Μετα–κλάσης (δες αντίστοιχο ένθετο πλαίσιο). Η

µετα–κλάση παρ’ ότι σηµαντικής σηµασίας, δεν υποστηρίζεται από πολλές

γλώσσες ΑΠ. Η συσχέτιση της Metaclass µε καθεµία από τις κλάσεις στιγ-

µιότυπα της είναι metaclass συσχέτιση.

ªÂÙ·–ÎÏ¿ÛË

Η κατασκευή της µετα–κλάσης µας επιτρέπει να χειριζόµαστε τις κλάσεις

σαν αντικείµενα. Μετα–κλάση είναι µια κλάση της οποίας τα στιγµιότυπα

είναι κλάσεις. Πλεονεκτήµατα της θεώρησης αυτής είναι αφενός η δυνα-

τότητα αποστολής µηνυµάτων σε µια κλάση για επηρεασµό όλων των στιγ-

µιότυπων της, αφετέρου η αναπαράσταση χαρακτηριστικών που είναι

κοινά για όλα τα στιγµιότυπα µιας κλάσης. Όπως ήδη είδαµε η Java, όπως

και η C++ που δεν υποστηρίζουν την έννοια της µετακλάσης, παρέχουν

αυτές τις δυνατότητες διαµέσου των µεταβλητών και µεθόδων κλάσης.

Έτσι, οι δηµιουργοί της C++ παρέχουν εναλλακτικό τρόπο έκφρασης των

λειτουργιών δηµιουργίας της µετα–κλάσης.

Σύµφωνα µε τον µηχανισµό της µετα–κλάσης, όλες οι κλάσεις έχουν το πρω-

τόκολλο που ορίζει η µετα–κλάση. Έτσι, για παράδειγµα, η λειτουργία «new»

ορίζεται στη µετα–κλάση. Η Smalltalk–78 διαθέτει µόνο µια µετα–κλάση για

όλες τις κλάσεις, αλλά η Smalltalk–80 δίνει τη δυνατότητα σε κάθε κλάση

να έχει τη µετα–κλάση της. Ο πολύ προχωρηµένος (advanced) προγραµµα-

τιστής µπορεί µέσα από την τροποποίηση των µετα–κλάσεων να µεταβάλει

το συντακτικό και τη σηµασιολογία της γλώσσας, κάτι φυσικά πολύ επικίν-

δυνο για το µέσου επιπέδου προγραµµατιστή. Ενδιαφέρον παρουσιάζει η

CLOS που παρέχοντας ισχυρότερη υποστήριξη στην έννοια της µετα–κλά-

σης επιτρέπει σηµαντικές επιδράσεις σε βασικά χαρακτηριστικά της. Αυτό

κάνει τη γλώσσα ιδανική για κατασκευή εργαλείων ανάπτυξης λογισµικού,

αλλά και για πειραµατισµούς µε εναλλακτικά αντικειµενοστρεφή στυλ προ-

γραµµατισµού. Στο τέλος της ενότητας 3.4 του [Booch 94] µπορείτε να βρεί-

τε µια καλή αναφορά στο προχωρηµένο αυτό θέµα.

Page 91: Γλώσσες Προγραμματισμού II

5.2 ¶ÚÔÛ‰ÈÔÚÈÛÙ¤˜ ÔÚ·ÙfiÙËÙ·˜

Περιγράψαµε την κλάση σαν µια συλλογή από δεδοµένα και µεθόδους και

αναφέραµε πως µια από τις βασικότερες αρχές του ΑΠ ορίζει, ότι τα δεδο-

µένα πρέπει να αποκρύπτονται στο εσωτερικό της κλάσης επιτρέποντας πρό-

σβαση σ’ αυτά µόνο διαµέσου των µεθόδων της. Αυτό εµποδίζει έναν εξω-

τερικό χρήστη, ο οποίος, έχοντας άµεση πρόσβαση, θα µπορούσε να τροπο-

ποιήσει ένα δεδοµένο αλλά να παραλείψει να τροποποιήσει άλλα σχετιζό-

µενα, µε αποτέλεσµα να αφήσει το αντικείµενο σε µια ασυνεπή κατάσταση

(inconsistent state). Αντίθετα, οι µέθοδοι έχουν αναπτυχθεί ώστε να κάνουν

το κάθε τι που είναι απαραίτητο για τη διατήρηση της συνέπειας της κατά-

στασης. Για την παραπέρα µελέτη του θέµατος της ορατότητας είναι σηµα-

ντικό να διακρίνουµε τους πελάτες µιας κλάσης σε δύο διαφορετικούς τύπους

• στιγµιότυπα

• υποκλάσεις

Η διάκριση αυτή οδήγησε στον ορισµό δύο διαφορετικών διεπαφών για τις

δύο αυτές κατηγορίες, καθώς διαφορετικές είναι οι ανάγκες της κάθε κατη-

γορίας. Γενικά, είναι επιθυµητό να εκτίθενται στη διάθεση των στιγµιότυ-

πων όλες οι εξωτερικά ορατές λειτουργίες, ενώ στη διάθεση των υποκλάσε-

ων ορισµένες βοηθητικές λειτουργίες και δεδοµένα. Έτσι το περιβάλλον υλο-

ποίησης θα πρέπει να διαθέτει µηχανισµούς προσδιορισµού της ορατότητας

των συστατικών µιας κλάσης προς τις δύο αυτές κατηγορίες. Στους µηχανι-

σµούς αυτούς περιλαµβάνονται οι λέξεις κλειδιά public, protected και private,

τις οποίες χρησιµοποιεί ο σχεδιαστής για να προσδιορίσει για κάθε στοιχείο,

αν αυτό θα είναι ορατό από τα στιγµιότυπα, τις κλάσεις απογόνους ή και τα

δύο. Ορισµένες βέβαια γλώσσες διαθέτουν περισσότερους βαθµούς ελευθε-

ρίας από άλλες. Έτσι, για την Smalltalk που διαθέτει λιγότερες δυνατότητες

ελέγχου της πρόσβασης από τις C++ και Java, οι µεταβλητές στιγµιότυπου

είναι ορατές από τις κλάσεις απογόνους, όχι όµως και από τα στιγµιότυπα.

Οι περισσότερες πάντως γλώσσες επιτρέπουν στον προγραµµατιστή, να

προσδιορίζει µε δική του ευθύνη την ορατότητα των µεταβλητών του. Προς

το σκοπό αυτό, διαθέτουν ένα σύνολο από προσδιοριστές, που χρησιµοποι-

ούµενοι κατάλληλα, ελέγχουν την ορατότητα δεδοµένων αλλά και µεθόδων.

Οι προσδιοριστές αυτοί για την Java είναι οι εξής:

public: Όταν εφαρµόζεται σε µια µέθοδο ή µεταβλητή, κάνει την µέθοδο ή

µεταβλητή ορατή από παντού.

9 1¶ ƒ √ ™ ¢ π √ ƒ π ™ ∆ ∂ ™ √ ƒ∞∆ √ ∆ ∏ ∆∞ ™

Page 92: Γλώσσες Προγραμματισμού II

9 2 ∫ ∂ º ∞ § ∞ π √ 5 : H K § ∞ ™ ∏ ™ ∞ ¡ ¢ √ ª π ∫ √ ™ ∆ √ π à ∂ π √ ∆ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

private: Eφαρµοζόµενη σε µεταβλητή περιορίζει την ορατότητα της µόνο

στις µεθόδους που ορίζονται στο εσωτερικό της κλάσης. Αντίστοιχα µια

private µέθοδος µπορεί να κληθεί µόνο από µεθόδους στο εσωτερικό της

κλάσης. Επιπλέον, private µεταβλητές και µέθοδοι δεν είναι ορατές από τις

κλάσεις απογόνους ούτε κληρονοµούνται απ’ αυτές.

protected: Προσδιορίζει µεθόδους και µεταβλητές ορατές µέσα στην κλάση

και τις απογόνους κλάσεις.

προεπιλεγµένη ορατότητα: Σε περίπτωση που δεν χρησιµοποιηθεί κανένας

από τους παραπάνω προσδιοριστές, η µεταβλητή ή η µέθοδος είναι ορατή

µέσα στην κλάση που ορίζεται, καθώς και στις υπόλοιπες κλάσεις του πακέ-

του που η κλάση ανήκει. Προσοχή! δεν είναι ορατή στις απογόνους κλάσεις,

εκτός βέβαια αν αυτές ανήκουν στο ίδιο πακέτο.

Σαν γενικό κανόνα θα σας συνιστούσαµε να χρησιµοποιείτε τους προσδιο-

ριστές protected και private protected για να αποκρύψετε µεθόδους και µετα-

βλητές από τα αντικείµενα που χρησιµοποιούν την κλάση σας, αλλά ταυτό-

χρονα να δώσετε την δυνατότητα σ’ αυτές να είναι πλήρως προσβάσιµες στις

απογόνους κλάσεις της.

Στον παρακάτω κώδικα συµπληρώστε τους προσδιοριστές ορατότητας στη

δήλωση της κλάσης C1, έτσι ώστε η µεταβλητή v1 και η µέθοδος m1 να

µπορούν να χρησιµοποιηθούν απ’ όλες τις κλάσεις του P1 αλλά και του P2,

ενώ η v2 και m2 να χρησιµοποιούνται µόνο για την υλοποίηση της C1.

∆ηλώστε στη συνέχεια τη µέθοδο m3 που θα µπορεί να χρησιµοποιηθεί

από τις κλάσεις C1, C2 και C3, τη µέθοδο m4 η οποία θα µπορεί να χρη-

σιµοποιηθεί από τις κλάσεις C1, C2 και C21, και τέλος τη µέθοδο m5 που

θα µπορεί να χρησιµοποιηθεί από τις κλάσεις C1, C2, C3 και C21. H λέξη

extends δηλώνει όπως θα δούµε στο Κεφάλαιο 6, πως η κλάση, το όνοµα

της οποίας είναι στα αριστερά της, είναι απόγονος της κλάσης, της οποίας

το όνοµα είναι στα δεξιά της. Μελετήστε την ενότητα 2.2 και κάντε τις

απαραίτητες διορθώσεις

package P1;

public class C1

………… .v1;

………… .m1()

ÕÛÎËÛËA˘ÙÔ·ÍÈÔÏfiÁËÛ˘

5.2

Page 93: Γλώσσες Προγραμματισμού II

9 3K ∞∆ ∏ ° √ ƒ π ∂ ™ ∫ § ∞ ™ ∂ ø ¡

………… .v2;

………… .m2()

class C2 extends C1

class C3

package P2;

import P1;

public class C21

class C22 extends C1

class C23

5.3 K·ÙËÁÔڛ˜ ÎÏ¿ÛˆÓ

Η εµβέλεια µιας κλάσης προσδιορίζει άµεσα βασικές ιδιότητες της κλάσης.

Οι κλάσεις όπως και οι µεταβλητές µπορούν να δηλωθούν µε διαφορετικές

εµβέλειες (δες ένθετο πλαίσιο) γεγονός που τις κατατάσσει σε τρεις κατη-

γορίες:

• κλάσεις δηλωµένες σε εµβέλεια πακέτου,

• κλάσεις δηλωµένες σε εµβέλεια κλάσης,

• κλάσεις δηλωµένες σε τοπική εµβέλεια.

∂Ì‚¤ÏÂÈ·

Η εµβέλεια (scope), που αποτελεί τη βάση της ενθυλάκωσης, ορίζει µια

περιοχή του προγράµµατος µέσα στην οποία οι κατασκευές της µεταβλη-

τής, της µεθόδου, της κλάσης, του interface ή του πακέτου µπορούν να

δηλωθούν και να χρησιµοποιηθούν. Έξω από την περιοχή αυτή, η κατα-

σκευή δεν είναι ορατή και δεν υπάρχει. Στόχος µας είναι να δηλώνουµε

προσεκτικά την ελάχιστη δυνατή περιοχή στην οποία η κάθε κατασκευή

χρησιµοποιείται, για να αποτρέψουµε κακή χρήση της από άλλες περιοχές.

O Winder [Winder 98] διακρίνει τις παρακάτω εµβέλειες:

(συνέχεια…)

Page 94: Γλώσσες Προγραμματισμού II

9 4 ∫ ∂ º ∞ § ∞ π √ 5 : H K § ∞ ™ ∏ ™ ∞ ¡ ¢ √ ª π ∫ √ ™ ∆ √ π à ∂ π √ ∆ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

5.3.1 ∫Ï¿ÛÂȘ ‰Ëψ̤Ó˜ Û ÂÌ‚¤ÏÂÈ· ·Î¤ÙÔ˘

Οι κλάσεις που δηλώνονται σε εµβέλεια πακέτου, που αποτελεί και την υψη-

λότερου επιπέδου εµβέλεια, ονοµάζονται υψηλού επιπέδου (top–level class)

και διακρίνονται από τις ένθετες (nested) κλάσεις, οι οποίες υπόκεινται σε

πρόσθετους κανόνες. Οι κλάσεις υψηλού επιπέδου µπορούν προαιρετικά να

δεχθούν τους παρακάτω προσδιορισµούς:

public: H κλάση έχει καθολική ορατότητα και µπορεί να χρησιµοποιηθεί από

(…συνέχεια)

Εµβέλεια προγράµµατος: Oνόµατα µ’ αυτή την εµβέλεια είναι προσβάσιµα

από κάθε πρόταση όλου του προγράµµατος. Εµβέλεια προγράµµατος δια-

θέτουν µόνο τα ονόµατα πακέτων.

Εµβέλεια πακέτου: Ένα πακέτο προσδιορίζει µια µονάδα ενθυλάκωσης.

Ονόµατα που δηλώνονται µέσα στο πακέτο µπορεί να είναι καθολικά στο

πακέτο, αλλά και προσβάσιµα από τους χρήστες του πακέτου. Ένα πακέ-

το µπορεί να χρησιµοποιηθεί από ένα άλλο, αλλά δεν µπορεί να ενσωµα-

τωθεί σ’ ένα άλλο.

Εµβέλεια µονάδας µεταγλώττισης: Σαν µονάδα µεταγλώττισης θεωρείται το

αρχείο (file). Ονόµατα µπορούν να είναι καθολικά σε επίπεδο αρχείου,

όπως και στην γλώσσα C. Όλα τα περιεχόµενα ενός αρχείου ανήκουν σ’

ένα πακέτο.

Εµβέλεια κλάσης: Oνόµατα που δηλώνονται µέσα σε µια κλάση είναι ορατά

σε κάθε άλλο τµήµα της κλάσης ή στις κλάσεις απογόνους της, εάν έχουν

δηλωθεί public ή protected. Αν δηλωθούν public είναι επιπλέον ορατά και

από τους χρήστες της κλάσης. Τέλος, αν δεν δηλωθούν public, protected ή

private είναι ορατά από τις άλλες κλάσεις του ίδιου πακέτου.

Τοπική εµβέλεια: Kάθε σύνθετη πρόταση προσδιορίζει τη δική της τοπική

εµβέλεια. Στην κατηγορία αυτή ανήκουν και τα σώµατα των µεθόδων, αλλά

και των προτάσεων ροής ελέγχου. Οι τοπικές εµβέλειες µπορούν να είναι

ένθετες (nested) σε οποιοδήποτε βάθος. Στην περίπτωση αυτή ονόµατα που

δηλώνονται µε τοπική εµβέλεια είναι ορατά µόνο στην περιοχή της εµβέ-

λειας και σε όλες τις ένθετες εµβέλειες. Ένα καλό παράδειγµα για την τοπι-

κή, αλλά και την εµβέλεια κλάσης που είναι και οι ευρύτερα χρησιµοποι-

ούµενες µπορείτε να βρείτε στην ενότητα 4.10 του [Deitel 98].

Page 95: Γλώσσες Προγραμματισμού II

κάθε άλλη κλάση. Για να χρησιµοποιηθεί βέβαια από κλάση άλλου πακέτου

πρέπει στο πηγαίο αρχείο που περιλαµβάνει την κλάση χρήστη να περιλη-

φθεί µια πρόταση import. Προσοχή στον περιορισµό της Java που επιτρέπει

µια µόνο public κλάση ή interface ανά αρχείο πηγαίου κώδικα.

abstract: Προσδιορίζει την κλάση που δεν έχει στιγµιότυπα. Χρησιµοποιεί-

ται για δήλωση κοινών µεθόδων και µεταβλητών που προορίζονται για χρήση

από τις κλάσεις απογόνους της. Μια τέτοια χρήση µπορεί να είναι είτε άµεση

είτε επανορισµός.

final: προσδιορίζει µια κλάση που δεν µπορεί να κληρονοµηθεί. Εάν για µια

κλάση η δηµιουργία απογόνων δεν έχει νόηµα ή είναι ανεπιθύµητη, ο προσ-

διοριστής final αναθέτει στο µεταγλωττιστή να αποτρέπει τη δηµιουργία απο-

γόνων, αλλά και να εφαρµόσει στατική διασύνδεση (static binding) αντί της

δυναµικής, βελτιώνοντας την απόδοση του παραγόµενου κώδικα.

5.3.2 ŒÓıÂÙ˜ ÎÏ¿ÛÂȘ

Ένθετες (nested) ή εσωτερικές (inner) είναι οι κλάσεις που δηλώνονται

µέσα σε άλλη εµβέλεια, η οποία συνήθως είναι εµβέλεια κλάσης, αλλά

µπορεί να είναι και τοπική εµβέλεια δηλαδή εµβέλεια σύνθετης πρότασης

ή σώµατος µεθόδου.

Κλάσεις δηλωµένες σε εµβέλεια κλάσης

Η δήλωση κλάσης µέσα σε άλλη κλάση έχει στόχο την απόκρυψη του τρό-

που υλοποίησης της περικλείουσας κλάσης. Kλάσεις δηλωµένες µέσα σε

άλλη κλάση δίνουν τη δυνατότητα µείωσης του αριθµού των κλάσεων σε

επίπεδο πακέτου, δηµιουργώντας ένα ακόµη επίπεδο απόκρυψης της κλάσης

κάτω από αυτό του πακέτου. Ο προσδιοριστής static έχει την ίδια επίδραση

όπως και στις µεθόδους και τις µεταβλητές.

Μια κλάση που δηλώνεται στο εσωτερικό µιας άλλης κλάσης µε τον προσ-

διοριστή static, υπόκειται στους κανόνες εµβέλειας και ενθυλάκωσης της κλά-

σης. Έτσι, αν οριστεί σαν private, είναι ορατή µόνο στο εσωτερικό τη κλάσης.

Μια ένθετη κλάση που δηλώνεται χωρίς τον προσδιοριστή static, είναι γνω-

στή σαν κλάση µέλους (member class). Είναι προφανές ότι ένα στιγµιότυπο

της κλάσης µέλους είναι άµεσα συσχετιζόµενο µε το στιγµιότυπο της περι-

κλείουσας κλάσης που το δηµιούργησε και αυτόµατα έχει µια άµεση αναφο-

ρά σ’ αυτό. Την αναφορά αυτή στο στιγµιότυπο της περικλείουσας κλάσης,

στην περίπτωση της Java, δηµιουργεί αυτόµατα ο µεταγλωττιστής. Έτσι το

9 5K ∞∆ ∏ ° √ ƒ π ∂ ™ ∫ § ∞ ™ ∂ ø ¡

Page 96: Γλώσσες Προγραμματισμού II

9 6 ∫ ∂ º ∞ § ∞ π √ 5 : H K § ∞ ™ ∏ ™ ∞ ¡ ¢ √ ª π ∫ √ ™ ∆ √ π à ∂ π √ ∆ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

στιγµιότυπο της κλάσης µέλους έχει άµεση πρόσβαση στις µεταβλητές του

στιγµιότυπου της περικλείουσας κλάσης. Για παράδειγµα στον πηγαίο κώδι-

κα του σχήµατος 5.1 η µέθοδος func της κλάσης C έχει πρόσβαση µε τη

χρήση του this στις µεταβλητές των κλάσεων που την περικλείουν.

class A

class B

class C

….

int c;

void func()

A.this.a // ·Ó·ÊÔÚ¿ ÛÙË ÌÂÙ·‚ÏËÙ‹ · Ù˘

// ÎÏ¿Û˘ ∞

B.this.b // ·Ó·ÊÔÚ¿ ÛÙË ÌÂÙ·‚ÏËÙ‹ b Ù˘

// ÎÏ¿Û˘ µ

this.c // ·Ó·ÊÔÚ¿ ÛÙË ÌÂÙ·‚ÏËÙ‹ c Ù˘ ÎÏ¿Û˘ C

….

int b;

int a;

™¯‹Ì· 5.1

Κλάσεις µέλους.

Κλάσεις δηλωµένες σε τοπική εµβέλεια

Μια κλάση που δηλώνεται µέσα στην εµβέλεια µιας σύνθετης πρότασης ή

µιας µεθόδου ονοµάζεται τοπική κλάση (local class). Μια τοπική κλάση µπο-

ρεί να θεωρηθεί σαν κλάση µέλους µε τους παρακάτω περιορισµούς:

α) ∆εν µπορεί να περιέχει στατικές µεταβλητές, µεθόδους ή κλάσεις και δεν

µπορεί να δηλωθεί public, protected, private ή static.

β) Eνώ µπορεί να χρησιµοποιήσει τη σύνταξη this, δεν µπορεί να χρησι-

µοποιήσει την αντίστοιχη new και super[2].

Page 97: Γλώσσες Προγραμματισμού II

Μια τοπική κλάση µπορεί να δηλωθεί χωρίς όνοµα, οπότε και ονοµάζεται

ανώνυµη κλάση. Η βασική χρήση της είναι για την άµεση δηµιουργία ενός

στιγµιότυπου, αποφεύγοντας την ανεξάρτητη δήλωση κλάσης. Αυτό γίνεται

χρησιµοποιώντας µια παραλλαγή της σύνταξης new, µε µόνο περιορισµό ότι

η κλάση πρέπει να είναι είτε υποκλάση είτε να υλοποιεί ένα interface.

Για µια αναλυτική περιγραφή των παραπάνω κατηγοριών κλάσεων µπορεί-

τε αν ανατρέξετε στις ενότητες 13.3 και 13.4 του [Winder 98], όπου θα βρεί-

τε και αντίστοιχα παραδείγµατα.

™‡ÓÔ„Ë

Η κλάση αποτελεί το βασικό δοµικό στοιχείο ενός αντικειµενοστρεφούς προ-

γράµµατος, καθώς το πρόγραµµα στο χρόνο µεταγλώττισης αποτελείται από

ένα σύνολο από δηλώσεις κλάσεων (και interfaces για την Java όπως θα

δούµε στο κεφάλαιο 6). Η χρήση των κατάλληλων προσδιοριστών στη δήλω-

ση της κλάσης, αλλά και η θέση της δήλωσης προσδιορίζουν την εµβέλεια της

κλάσης. Ανάλογα, ισχύουν και για τις δηλώσεις µεταβλητών και µεθόδων,

όπου οι προσδιοριστές ορίζουν, αν η κατασκευή είναι προσβάσιµη από τα

στιγµιότυπα της κλάσης και/ή από τις κλάσεις απογόνους. Σαν γενικό κανό-

να θα πρέπει να δηλώνουµε όλες τις µεταβλητές στιγµιότυπου private. Περιο-

ρίζουµε µε τον τρόπο αυτό όλα τα προβλήµατα της διαχείρισης των δεδοµέ-

νων του αντικειµένου στο εσωτερικό του, διευκολύνοντας την εκσφαλµάτω-

ση (debugging). ∆ηµιουργήστε κατάλληλες µεθόδους για ανάγνωση και/ή

τροποποίηση των τιµών των private µεταβλητών µόνο όταν αυτό είναι απα-

ραίτητο. Η τεχνική αυτή µειώνει τα λάθη και αυξάνει τον βαθµό µετατρεψι-

µότητας (modifiability) του προγράµµατος.

Για τον ίδιο ακριβώς λόγο ορίστε ένθετες τις κλάσεις που συµµετέχουν µόνο

στην υλοποίηση µια άλλης κλάσης. Χρησιµοποιήστε την ανώνυµη κλάση όταν

θέλετε µόνο ένα στιγµιότυπο της εν λόγω κλάσης.

9 7™ Y N O æ H

[2] H δεσµευµένη λέξη super µας επιτρέπει, όπως θα δούµε στο Κεφάλαιο 6, να

καλέσουµε τον δηµιουργό της προγόνου κλάσης.

Page 98: Γλώσσες Προγραμματισμού II

9 8 ∫ ∂ º ∞ § ∞ π √ 5 : H K § ∞ ™ ∏ ™ ∞ ¡ ¢ √ ª π ∫ √ ™ ∆ √ π à ∂ π √ ∆ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ √ ™

BÈ‚ÏÈÔÁÚ·Ê›·

[1] [Booch 94]

Grady Booch, «Object–Oriented Analysis and Design with

applications», second edition, Benjamin/Cummings Publishing

Company Inc, 1994.

[2] [Rumbaugh 91]

J. Rumbaugh, et.al «Object–Oriented Modeling and Design», Prentice

Hall International, 1991.

Αποτελεί το κλασικό, θα έλεγα, βιβλίο, στο οποίο η αντικειµενοστρε-

φής προσέγγιση οφείλει την εξάπλωση της. Σαν βασικό εγχειρίδιο της

OMT (Object Modeling Technique) µεθοδολογίας, της περισσότερο χρη-

σιµοποιούµενης µεθοδολογίας πριν την εµφάνιση της UML, είναι απο-

δεκτό για την απλότητα µε την οποία εισάγει τις βασικότερες έννοιες

της ΑΠ. Αν και πολλά από τα στοιχεία που παρουσιάζει αποτελούν

πλέον παρελθόν για την ΑΠ, όπως το functional model, παρ’όλα αυτά

χρησιµοποιείται σαν αναφορά για τις βασικές έννοιες της αντικειµενο-

στρεφούς προσέγγισης όπως links, associations, aggregation, inheritance,

dynamic modeling, κ.λ.π.

[3] [Winder 98]

Rusel Winder, Graham Roberts, «Developing Java Software», John

Wiley & Sons, 1998.

Το βιβλίο εισάγει βασικές έννοιες του αντικειµενοστρεφούς προγραµ-

µατισµού, χρησιµοποιώντας πολυάριθµα παραδείγµατα. Το βασικό στοι-

χείο που το διαφοροποιεί από την πληθώρα των βιβλίων που αναφέρο-

νται στην Java, είναι η ιδιαίτερη έµφαση που δίνει στο σχεδιασµό προ-

γράµµατος µε στόχο την ανάπτυξη εύρωστων (robust) και αξιόπιστων

(reliable) εφαρµογών. Εκτός αυτού, το βιβλίο µπορεί να χρησιµοποιη-

θεί και σαν αναφορά στην Java, καθώς καλύπτει επιτυχώς µε πολλά

µικρά παραδείγµατα όλα τα χαρακτηριστικά της γλώσσας.

Page 99: Γλώσσες Προγραμματισμού II

KÏËÚÔÓÔÌÈÎfiÙËÙ·

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να παρουσιάσει το µηχανισµό της κληρονοµι-

κότητας και τον τρόπο µε τον οποίο αυτός χρησιµοποιείται για να αυξήσει

αφενός την επαναχρησιµοποίηση, αφετέρου διαµέσου του πολυµορφισµού,

την επεκτασιµότητα των συστηµάτων λογισµικού.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• εξηγήσετε τι είναι απλή και τι πολλαπλή κληρονοµικότητα,

• περιγράψετε τις απαραίτητες ενέργειες για την προσθήκη µιας νέας κλά-

σης στο σύστηµα,

• δώσετε δύο τουλάχιστον παραδείγµατα πολλαπλής κληρονοµικότητας,

• εξηγήσετε µε δικά σας λόγια τι σηµαίνει πολυµορφισµός,

• περιγράψετε το µηχανισµό κλήσης µεθόδου σ’ ένα αντικειµενοστρεφές

σύστηµα,

• εξηγήσετε πώς οι δηµιουργοί µιας υποκλάσης χρησιµοποιούν τους δηµι-

ουργούς των κλάσεων προγόνων,

• αναφέρετε πώς µια κλάση απόγονος µπορεί να χρησιµοποιεί µεταβλητές

και µεθόδους ίδιου ονόµατος µ’ αυτές των προγόνων κλάσεων της,

• δώσετε από ένα τουλάχιστον παράδειγµα επικαλυπτόµενης µεταβλητής και

υπερκαλυπτόµενης µεθόδου,

• περιγράψετε πώς η Java υποστηρίζει την πολλαπλή κληρονοµικότητα.

ŒÓÓÔȘ ÎÏÂȉȿ

6∫ ∂ º ∞ § ∞ π √

• απλή κληρονοµικότητα

• πολλαπλή κληρονοµικότητα

• υπερκλάση (superclass)

• υποκλάση (subclass)

• βασική κλάση (baseclass)

• inheritance tree

• Object based

• πολυµορφισµός

(polymorphism)

• πρώιµη διασύνδεση

(early binding)

Page 100: Γλώσσες Προγραμματισμού II

1 0 0 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Στο προηγούµενο κεφάλαιο αναφέραµε την κληρονοµικότητα σαν τον πιο

ενδιαφέροντα τύπο συσχέτισης µεταξύ των κλάσεων. Στο κεφάλαιο αυτό θα

αναφερθούµε αναλυτικά στο µηχανισµό της γλώσσας που υποστηρίζει την

υλοποίηση αυτής της συσχέτισης και στον τρόπο που αυτός επηρεάζει την

ανάπτυξη του λογισµικού.

Κάθε αντικειµενοστρεφές περιβάλλον ανάπτυξης συνοδεύεται από µια βιβλιο-

θήκη έτοιµων προς χρήση κλάσεων. Τις κλάσεις αυτές, που η Java προσφέρει

σαν βασική βιβλιοθήκη κλάσεων, έχετε χρησιµοποιήσει και υποθέτω πως έχετε

ήδη πεισθεί πως η δυνατότητα χρησιµοποίησης της βασικής βιβλιοθήκης, αλλά

και άλλων έτοιµων βιβλιοθηκών αποτελεί απαραίτητη προϋπόθεση για την

ανάπτυξη αξιόλογων αντικειµενοστρεφών προγραµµάτων. Χρησιµοποιείτε τις

κλάσεις δηµιουργώντας στιγµιότυπα και αποστέλλοντας µηνύµατα σ’ αυτά

(µέθοδοι στιγµιότυπου), αλλά και στις κλάσεις (µέθοδοι κλάσης). Η χρήση

αυτή αναφέρεται σαν άµεση χρήση. Στο κεφάλαιο αυτό θα περιγράψουµε πώς

η κληρονοµικότητα µας παρέχει ένα δεύτερο έµµεσο τρόπο χρήσης των κλά-

σεων της βασικής βιβλιοθήκης του περιβάλλοντος ανάπτυξης. Μάλιστα θα

δούµε πως αυτός ο δεύτερος τρόπος αυξάνει την αποτελεσµατικότητα της επα-

ναχρησιµοποίησης και αποτελεί ένα από τα ισχυρότερα πλεονεκτήµατα της

ΑΠ. Είναι λοιπόν προφανές ότι θα πρέπει να δώσετε ιδιαίτερη προσοχή στο

κεφάλαιο αυτό, καθώς ο προγραµµατισµός χωρίς χρήση κληρονοµικότητας

δεν είναι σε καµία περίπτωση αντικειµενοστρεφής προγραµµατισµός.

Η πρώτη ενότητα, αναφέρεται στην απλή κληρονοµικότητα, στον τρόπο µε

τον οποίο αυτή χρησιµοποιείται για να αυξήσει την επαναχρησιµοποίηση και

τις απαραίτητες αναδοµήσεις των δένδρων κληρονοµικότητας, κατά την διάρ-

κεια ανάπτυξης του προγράµµατος. Στη δεύτερη ενότητα, γίνεται µια πολύ

σύντοµη αναφορά στην πολλαπλή κληρονοµικότητα, ένα χαρακτηριστικό της

ΑΠ για το οποίο υπάρχουν πολλές αντικρουόµενες απόψεις, όσον αφορά την

χρήση της. Στην τρίτη ενότητα, αναφερόµαστε στην ικανότητα στιγµιότυπων

διαφορετικών κλάσεων να αποκρίνονται στο ίδιο µήνυµα µε διαφορετικό

τρόπο. Το χαρακτηριστικό αυτό, γνωστό σαν πολυµορφισµός, βασίζεται στο

• όψιµη διασύνδεση

(late binding)

• επικάλυψη µεταβλητής

• υπερκάλυψη µεθόδου

Page 101: Γλώσσες Προγραμματισμού II

µηχανισµό της κληρονοµικότητας αλλά και της όψιµης διασύνδεσης και αυξά-

νει την ευελιξία στη διαχείριση των αντικειµένων. Τέλος, στην τέταρτη ενό-

τητα περιγράφουµε πώς η Java υποστηρίζει τα χαρακτηριστικά που αναφέρ-

θηκαν στις προηγούµενες ενότητες.

6.1 ∞Ï‹ ÎÏËÚÔÓÔÌÈÎfiÙËÙ·

6.1.1 °ÂÓÈο

Η κληρονοµικότητα είναι ο µηχανισµός του περιβάλλοντος υλοποίησης που

µας επιτρέπει αφενός να υλοποιήσουµε τη σχέση γενίκευσης–εξειδίκευσης

µεταξύ των εννοιών της περιοχής του προβλήµατος (problem space), αφε-

τέρου να αναπτύξουµε νέες κλάσεις της περιοχής λύσης του προβλήµατος

(solution space), οι οποίες θα κληρονοµούν χαρακτηριστικά από άλλες ήδη

υπάρχουσες κλάσεις. Οι νέες αυτές κλάσεις κληρονοµούν τη δοµή ή/και τη

συµπεριφορά που ορίζεται σε µία (απλή κληρονοµικότητα, single

inheritance) ή περισσότερες (πολλαπλή κληρονοµικότητα, multiple

inheritance) άλλες κλάσεις. Την κλάση από την οποία κληρονοµούν ονοµά-

ζουµε υπερκλάση (superclass), ενώ αυτή που κληρονοµεί ονοµάζεται υπο-

κλάση (subclass). Η κληρονοµικότητα εφαρµοζόµενη σε διαδοχικά επίπεδα

οδηγεί σ’ ένα σχήµα όπως αυτό του σχήµατος 6.1 που είναι γνωστό µε το

όνοµα δένδρο κληρονοµικότητας (inheritance tree). Η κλάση στη ρίζα του

δένδρου ονοµάζεται βασική κλάση (base class). Ένα πρόγραµµα αποτελεί-

ται συνήθως από περισσότερες της µιας βασικές κλάσεις, οι οποίες αναπα-

ριστούν τις σηµαντικότερες αφαιρέσεις της περιοχής του προβλήµατος. Έτσι,

ένα καλοσχεδιασµένο πρόγραµµα, αποτελείται από πολλά δένδρα ιεραρχίας.

Στην πράξη, τα περισσότερα περιβάλλοντα υλοποίησης έχουν ορισµένη µια

βασική κλάση (συνήθως µε όνοµα Object), η οποία λειτουργεί σαν θεµε-

λιώδης υπερκλάση όλων των άλλων κλάσεων.

1 0 1∞ ¶ § ∏ ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

Shape

EllipseRectangle Triangle

Circle

™¯‹Ì· 6.1

∆ένδρο

κληρονοµικότητας.

Page 102: Γλώσσες Προγραμματισμού II

1 0 2 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

H σχέση της κληρονοµικότητας είναι γνωστή και σαν «is–a» σχέση γεγονός

που µπορεί να χρησιµοποιηθεί σαν ένα πρακτικό τεστ για την αναγνώρισή

της. Με δεδοµένες τις κλάσεις Α και Β, εάν η Α δεν είναι ένα (is not a) είδος

της Β, τότε η Α δεν µπορεί να είναι υποκλάση της Β. Η υποστήριξη της κλη-

ρονοµικότητας µε αυτή την µορφή, αποτελεί βασικό χαρακτηριστικό της ΑΠ

και διακρίνει µια αντικειµενοστρεφή (Object Oriented) από µία βασισµένη

σε αντικείµενα (Object based) γλώσσα προγραµµατισµού.

Το µεγάλο πλεονέκτηµα της κληρονοµικότητας είναι η αύξηση της επανα-

χρησιµο–ποίησης των διαθέσιµων κλάσεων. Αυτό βέβαια προϋποθέτει την

τοποθέτηση των περισσότερο γενικών κλάσεων στην κορυφή της ιεραρχίας,

ενώ χαµηλά τοποθετούνται οι περισσότερο εξειδικευµένες. Το πιο σηµαντι-

κό είναι ότι, όταν αναφερόµαστε σε υπάρχουσες κλάσεις, δεν εννοούµε µόνο

αυτές που αναπτύσσονται στα πλαίσια του υπό ανάπτυξη συστήµατος, αλλά

και κλάσεις προηγούµενων συστηµάτων και κυρίως κλάσεις των βιβλιοθη-

κών που συνήθως συνοδεύουν τα αντικειµενοστρεφή περιβάλλοντα ανά-

πτυξης. Αναφερθήκαµε ήδη στη βιβλιοθήκη κλάσεων της Java. Αντίστοιχες

βιβλιοθήκες διαθέτουν οι Smalltalk, Eiffel, Objective–C και C++.

6.1.2 ¶ÚÔÛı‹ÎË Ó¤·˜ ÎÏ¿Û˘

Κατά τη διάρκεια της ανάπτυξης του προγράµµατος, νέες κλάσεις εντοπίζο-

νται και ορίζονται. Για τον ορισµό µιας νέας κλάσης έχουµε σύµφωνα µε τον

Ivar Jacobson [Jacobson 93] τις παρακάτω επιλογές:

1. Oρίζουµε τη νέα κλάση εξ αρχής χωρίς να εκµεταλλευθούµε τα ήδη υπάρ-

χοντα δένδρα κληρονοµικότητας.

2. Eπιλέγουµε το πλέον κατάλληλο δένδρο κληρονοµικότητας και µετακι-

νούµαστε από κάτω προς τα πάνω στην ιεραρχία µέχρι να εντοπίσουµε

µια κατάλληλη πρόγονο[1] της νέας κλάσης.

3. Aναδοµούµε την ιεραρχία κληρονοµικότητας, ώστε να δηµιουργήσουµε

µια κατάλληλη πρόγονο.

4. Eπανορίζουµε τα χαρακτηριστικά που δεν θέλουµε να κληρονοµηθούν

ως έχουν.

Στην πρώτη περίπτωση, η νέα κλάση δεν έχει να κληρονοµήσει κάτι από τις

υπάρχουσες και συνεπώς την ορίζουµε χωρίς να εκµεταλλευθούµε την κλη-

[1] Mια κλάση που έχει τα χαρακτηριστικά που θέλουµε η νέα µας κλάση να κλη-

ρονοµήσει.

Page 103: Γλώσσες Προγραμματισμού II

ρονοµικότητα. Στη δεύτερη περίπτωση υπάρχει ένα δένδρο κληρονοµικότη-

τας µε κλάσεις που διαθέτουν ανάλογα χαρακτηριστικά µε την προς ορισµό

κλάση. Ας υποθέσουµε πως έχουµε την ιεραρχία του σχήµατος 6.2(α) και

πως η νέα µας κλάση πρέπει να έχει τα χαρακτηριστικά Α και Κ. Κινούµα-

στε από κάτω προς τα πάνω, έως ότου εντοπίσουµε µια κατάλληλη πρόγονο

κλάση. Στην περίπτωσή µας αυτή είναι η Α και η ιεραρχία διαµορφώνεται

όπως στο σχήµα 6.2(β).

1 0 3∞ ¶ § ∏ ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

+ BC

=(ABC)

+ D

=(A D)

+ E

=(ABCE)

+ F

=(ABCF)

A

(α) (β)

+ BC

=(ABC)

+ D

=(A D)

+ E

=(ABCE)

+ F

=(ABCF)

A

+ K

=(A K)

™¯‹Ì· 6.2

Ενσωµάτωση κλάσης

στην ιεραρχία

κληρονοµικότητας.

+ B

=(A B)

+ D

=(A D)

+ C

=(ABC)

+ K

=(ABK)

A

+ E

=(ABCE)

+ F

=(ABCF)

™¯‹Ì· 6.3

Ενσωµάτωση κλάσης µε

αναδόµηση της ιεραρχίας

κληρονοµικότητας

Ας υποθέσουµε τώρα πως η νέα κλάση πρέπει να έχει σαν χαρακτηριστικά

τα Α, Β και Κ. Για να διατηρήσουµε µια καλή ιεραρχία, θα πρέπει να ανα-

δοµήσουµε το δένδρο το οποίο µπορεί να πάρει µια µορφή σαν αυτήν του

σχήµατος 6.3. Η αναδόµηση αυτή απαιτεί αφενός προσπάθεια για ανεύρεση

της κατάλληλης ιεραρχίας, αφετέρου αλλαγές στο µέχρι τώρα αναπτυχθέν

πρόγραµµα, το οποίο προφανώς βασίστηκε στην υπάρχουσα ιεραρχία.

Η τελευταία περίπτωση που είναι γνωστή µε το όνοµα υπερκάλυψη

(overriding), περιλαµβάνει τον επανορισµό συµπεριφοράς ή/και δοµής της

προγόνου κλάσης. Ο επανορισµός, βοηθά στην εν µέρει επαναχρησιµοποί-

ηση, καθώς περιλαµβάνει τροποποίηση της συµπεριφοράς προγόνων κλά-

σεων, δηµιουργεί όµως προβλήµατα στην κατανόηση της ιεραρχίας, καθώς

λειτουργίες µε το ίδιο όνοµα µπορούν να έχουν διαφορετική σηµασία σε δια-

φορετικές κλάσεις. Για το λόγο αυτό, δεν είναι λίγοι αυτοί που υποστηρίζουν

πως µια τέτοια χρήση πρέπει να αποφεύγεται. Μια καλή µελέτη του θέµα-

τος της κληρονοµικότητας και του τρόπου χρήσης της, µπορείτε να βρείτε

στην ενότητα 3.5.1 του [Jacobson 93], στην οποία σας συνιστώ να ανατρέ-

ξετε µετά την ολοκλήρωση του κεφαλαίου. Στην ίδια ενότητα θα βρείτε και

Page 104: Γλώσσες Προγραμματισμού II

1 0 4 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

τον ορισµό του όρου «spaghetti inheritance» που χαρακτηρίζει την ακραία

εφαρµογή της κληρονοµικότητας µεταξύ κλάσεων που δεν σχετίζονται, µε

µόνο λόγο την επαναχρησιµοποίηση ελάχιστων λειτουργιών.

6.2 ¶ÔÏÏ·Ï‹ ÎÏËÚÔÓÔÌÈÎfiÙËÙ·

Πολλές φορές καθώς περιγράφουµε µια νέα κλάση, διαπιστώνουµε πως αυτή

έχει χαρακτηριστικά δύο ή περισσότερων άλλων κλάσεων. Αν το περιβάλ-

λον υλοποίησης υποστηρίζει πολλαπλή κληρονοµικότητα (multiple

inheritance), µπορούµε να ορίσουµε τη νέα κλάση κληρονοµώντας τα χαρα-

κτηριστικά δύο ή περισσότερων κλάσεων. Έτσι, αν έχουµε τις δύο κλάσεις

µε χαρακτηριστικά ΧΥΖ και ΚΛΜ και θέλουµε να δηµιουργήσουµε µια νέα

µε χαρακτηριστικά ΥΜ, µπορούµε να αναδοµήσουµε τις κλάσεις και να ορί-

σουµε τη νέα κλάση σαν απόγονο δύο άλλων κλάσεων, από τις οποίες θα

κληρονοµεί τα Υ και Μ όπως φαίνεται στο σχήµα 6.4.

XYZ Y M

YM

νέα κλάση

KΛM

(α) (β)

+ XZ

=(XYZ)=(YM)

+ KΛ

=(KΛM)

™¯‹Ì· 6.4

Πολλαπλή κληρονοµικό-

τητα. Μια κλάση κληρονο-

µεί από δύο ή περισσότε-

ρες κλάσης.

Αν και οι απόψεις των ερευνητών της ΑΠ για την πολλαπλή κληρονοµικό-

τητα είναι αντιφατικές, είναι κοινά αποδεκτό, ότι αυτή αποτελεί πηγή δηµι-

ουργίας πολλών προβληµάτων και η χρήση της πρέπει να γίνεται µε µεγάλη

προσοχή και µόνο από πεπειραµένους προγραµµατιστές. Αν θέλετε περισ-

σότερα για την πολλαπλή κληρονοµικότητα µπορείτε να ανατρέξετε στην

ενότητα 4.4 του [Rumbaugh 91], όπου θα βρείτε µια προσιτή προσέγγιση

του θέµατος.

6.3 ¶ÔÏ˘ÌÔÚÊÈÛÌfi˜

Θα θεωρήσουµε ένα γραφικό περιβάλλον διαχείρισης γεωµετρικών σχηµά-

των. Σ’ ένα από τα παράθυρά του ο χρήστης έχει δηµιουργήσει διάφορα γεω-

µετρικά σχήµατα, όπως φαίνεται στο σχήµα 6.5. Στη συνέχεια ο χρήστης

ανοίγει ένα νέο παράθυρο που εν µέρει καλύπτει το προηγούµενο και δηµι-

Page 105: Γλώσσες Προγραμματισμού II

ουργεί και σ’ αυτό διάφορα γεωµετρικά σχήµατα. Θέλοντας να επαναφέρει

µπροστά το πρώτο παράθυρο, το επιλέγει και ενεργοποιεί την επιλογή του

προγράµµατος «Bring to Front». Αυτό έχει σαν αποτέλεσµα την αποστολή

στο παράθυρο ενός µηνύµατος draw. Η αντίδραση του παραθύρου στο µήνυ-

µα αυτό, ορίζεται πλήρως από τη µέθοδο µε το αντίστοιχο όνοµα. Η µέθο-

δος θα πρέπει να φέρει το παράθυρο µε τα περιεχόµενα του «µπροστά». Για

να επιτύχει κάτι τέτοιο, ο προγραµµατιστής θα πρέπει να την ορίσει, έτσι

ώστε να αποστέλλει το µήνυµα draw σε κάθε γεωµετρικό σχήµα που περιέ-

χει. Κάθε σχήµα µε τη σειρά του, λαµβάνοντας το µήνυµα ζωγραφίζει τον

εαυτό του όπως, η δική του κλάση ορίζει. Η µέθοδος της κλάσης παράθυρο

στέλνει το µήνυµα draw χωρίς να γνωρίζει την κλάση του στιγµιότυπου

παραλήπτη. Το γεγονός ότι ο αποστολέας ενός µηνύµατος δε χρειάζεται να

γνωρίζει την κλάση του στιγµιότυπου παραλήπτη, ονοµάζουµε πολυµορφι-

σµό (polymorphism). Ένας πιο πρακτικός ορισµός αναφέρει ως πολυµορφι-

σµό το γεγονός, ότι µια λειτουργία µπορεί να υλοποιηθεί µε διαφορετικό

τρόπο από διάφορες κλάσεις. Έτσι, η λειτουργία draw έχει διαφορετική υλο-

ποίηση στην κλάση κύκλος από ότι στην κλάση τρίγωνο, κ.ο.κ. Η αφηρη-

µένη κλάση shape του σχήµατος 6.1 ορίζει τη διεπαφή της λειτουργίας draw

και η κάθε απόγονος κλάση ορίζει τη δική της υλοποίηση.

1 0 5¶ √ § À ª √ ƒ º π ™ ª √ ™

Bring to Front

draw

draw

draw

draw

draw

™¯‹Ì· 6.5

Πολυµορφική

συµπεριφορά

αντικειµένων.

Στη επόµενη ενότητα θα δούµε πώς µπορούµε να εκµεταλλευθούµε τα πλε-

ονεκτήµατα του πολυµορφισµού για την ανάπτυξη ευέλικτου κώδικα.

Page 106: Γλώσσες Προγραμματισμού II

1 0 6 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

∫Ï‹ÛË ÌÂıfi‰Ô˘

Στις παραδοσιακές γλώσσες προγραµµατισµού, η κλήση ενός υποπρο-

γράµµατος (συνάρτησης, ρουτίνας) είναι µια πλήρως στατική δραστηριό-

τητα. Έτσι, στη C για την κλήση της συνάρτησης func ο µεταγλωττιστής

δηµιουργεί κώδικα που µεταφέρει τον έλεγχο στο σηµείο που αρχίζει ο κώδι-

κας της func. Αντίθετα, σε γλώσσες όπως οι Smalltalk, C++, Java κ.λπ., που

υποστηρίζουν κάποια µορφή πολυµορφισµού, η κλάση του αντικειµένου

στο οποίο αποστέλλεται το µήνυµα δεν είναι γνωστή παρά µόνο κατά τη

διάρκεια εκτέλεσης του προγράµµατος. Αυτό απαγορεύει την πρώιµη δια-

σύνδεση (early binding), τη διασύνδεση δηλαδή στο χρόνο µεταγλώττισης,

επιβάλλοντας τη χρήση µιας πιο σύνθετης τεχνικής που είναι γνωστή σαν

δυναµική διασύνδεση. Επειδή η δυναµική αυτή διασύνδεση λαµβάνει χώρα

κατά το χρόνο εκτέλεσης του προγράµµατος ονοµάζεται και όψιµη διασύν-

δεση (late binding). Σε κάθε περίπτωση που δεν παρεµβάλλεται κληρονο-

µικότητα, αλλά και σ’ αυτές που παρεµβάλλεται χωρίς χρήση πολυµορφι-

σµού, η κλήση των µεθόδων είναι ανάλογη της στατικής κλήσης.

Στη συνέχεια θεωρούµε την ιεραρχία του σχήµατος 6.1, όπου η κλάση

Shape διαθέτει µια µεταβλητή center και τις µεθόδους setCenter και draw.

Είναι προφανές ότι η µέθοδος setCenter είναι κοινή για όλες τις υποκλά-

σεις της Shape και ως εκ τούτου µπορεί να υλοποιηθεί στην κλάση Shape.

Αντίθετα, κάθε υποκλάση πρέπει να έχει την δική της ξεχωριστή υλοποίη-

ση της draw και έτσι η µέθοδος αυτή δεν µπορεί να υλοποιηθεί στην Shape.

Θεωρήστε τώρα το παρακάτω τµήµα κώδικα:

Shape[] shapes = new Shape[10];

shapes[0] = new Circle(); // Ù· ÛÙÔȯ›· ÙÔ˘ ›Ó·Î·

ÂÓËÌÂÚÒÓÔÓÙ·È Ì ·Ó·ÊÔÚ¤˜

shapes[1] = new …….. // ÛÂ ÛÙÈÁÌÈfiÙ˘· Circle,

Rectangle, Triangle

………

(συνέχεια…)

Αφού µελετήσετε καλά τα περί κληρονοµικότητας, αλλά και το πλαίσιο

που επεξηγεί τον τρόπο κλήσης µεθόδου, προσπαθήστε να σχολιάστε την

επίδραση της κληρονοµικότητας στην απόκρυψη πληροφορίας. Τα δικά µας

σχόλια θα βρείτε στο τέλος του κεφαλαίου.

¢Ú·ÛÙËÚÈfiÙËÙ·6.1

Page 107: Γλώσσες Προγραμματισμού II

(…συνέχεια)

Είναι προφανές ότι ο πίνακας shapes είναι ανοµοιογενής, περιέχει δηλαδή

στιγµιότυπα των οποίων η κλάση είναι άγνωστη στο χρόνο µεταγλώττισης.

Αν ένα αντικείµενο θέλει να ζωγραφίσει τα στιγµιότυπα του πίνακα shapes,

θα πρέπει να πάρει ένα–ένα τα στοιχεία του και να αποστείλει σε καθένα

το µήνυµα draw. Χρησιµοποιώντας την πρόταση for o κώδικας που υλο-

ποιεί την παραπάνω διεργασία θα έχει την µορφή

ffoorr((iinntt ii==00;; ii<<1100;;ii++++))

sshhaappeess[[ii]]..ddrraaww(());;

Είναι προφανές, ότι το αντικείµενο που αποστέλλει το µήνυµα draw δεν

γνωρίζει τον τύπο του κάθε στοιχείου του πίνακα. Επιπλέον, ο µεταγλωτ-

τιστής, µη γνωρίζοντας τον τύπο του κάθε στιγµιότυπου του πίνακα, δεν

µπορεί να καλέσει την κατάλληλη µέθοδο και αναβάλλει τη διασύνδεση

για το χρόνο εκτέλεσης. Στο σηµείο αυτό παρατηρούµε διαφορετικές

συµπεριφορές από τις διάφορες γλώσσες προγραµµατισµού. Μια αναλυτι-

κή αναφορά για το πώς ακριβώς αντιµετωπίζουν το θέµα οι Smalltalk, C++

και CLOS µπορείτε να βρείτε στο κεφάλαιο 3 σελίδα 119 του [Booch 94].

Εµείς θα περιγράψουµε στη συνέχεια τη βασική λογική πάνω στην οποία

βασίζεται αυτός ο µηχανισµός της όψιµης διασύνδεσης. Το στιγµιότυπο παρα-

λήπτης, όταν δέχεται το µήνυµα draw, καθώς γνωρίζει τον τύπο του, ανατρέ-

χει στην αντίστοιχη κλάση, όπου αναζητά την κατάλληλη µέθοδο. Αν τη βρει

την εκτελεί, όπως συµβαίνει µε τη µέθοδο draw, η οποία είναι υλοποιηµένη

σε κάθε υποκλάση. Αν δεν τη βρει, όπως θα συνέβαινε µε την setCenter, θα

µετακινηθεί στην ιεραρχικά ανώτερη κλάση, στην ιεραρχία και θα αναζητή-

σει εκεί τη µέθοδο. Αν τη βρει, την εκτελεί, διαφορετικά συνεχίζει την ανα-

ζήτηση µέχρι να φτάσει στη βασική κλάση την οποία κληρονοµούν όλες οι

κλάσεις, την κλάση Object για την Java. Αν η µέθοδος δε βρεθεί στη βασική

κλάση, υπάρχουν δύο επιλογές: είτε δηµιουργείται ένα µήνυµα λάθους, είτε

η κλήση αγνοείται και η εκτέλεση συνεχίζεται µε την επόµενη πρόταση.

Σε περίπτωση βέβαια κλήσης της setCircle θα ήταν δυνατό να έχουµε στατική

κλήση, αφού έχουµε µια µέθοδο κοινή για όλα τα στιγµιότυπα. Κάτι τέτοιο ανι-

χνεύεται από µεταγλωττιστές των οποίων οι γλώσσες διαθέτουν τον αντίστοι-

χο µηχανισµό, µε αποτέλεσµα τη βελτίωση της απόδοσης του προγράµµατος.

(συνέχεια…)

1 0 7¶ √ § À ª √ ƒ º π ™ ª √ ™

Page 108: Γλώσσες Προγραμματισμού II

1 0 8 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

(…συνέχεια)

Είναι σηµαντικό επίσης, να επισηµάνουµε στο σηµείο αυτό, την επιβά-

ρυνση (overhead) σε χρόνο που επιφέρει η δυναµική διασύνδεση σε σχέση

µε τη στατική. Η επιβάρυνση αυτή σε ορισµένα συστήµατα είναι ανεπιθύ-

µητη, οπότε θα πρέπει να αναζητήσουµε και να χρησιµοποιήσουµε τεχνι-

κές αποφυγής της.

6.4 H ÎÏËÚÔÓÔÌÈÎfiÙËÙ· ÛÙË Java

™ÎÔfi˜

Σκοπός της ενότητας είναι να παρουσιάσει τις κατασκευές και τους µηχανι-

σµούς της Java που υποστηρίζουν την απλή και την πολλαπλή κληρονοµικό-

τητα δίνοντας ταυτόχρονα και τον τρόπο χρήσης τους στην ανάπτυξη προ-

γράµµατος.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• χρησιµοποιείτε τις κλάσεις της βασικής βιβλιοθήκης τροποποιώντας ή επε-

κτείνοντας την συµπεριφορά τους,

• δηλώνετε κλάσεις οι οποίες θα κληρονοµούν χαρακτηριστικά κλάσεων της

βασικής βιβλιοθήκης αλλά και γενικότερα οποιασδήποτε διαθέσιµης κλάσης,

• ορίζετε αφηρηµένες κλάσεις οι οποίες θα σας επιτρέπουν να εκµεταλλευ-

θείτε τα πλεονεκτήµατα του πολυµορφισµού,

• ορίσετε δηµιουργούς στις κλάσεις σας επαναχρησιµοποιώντας τους δηµι-

ουργούς των προγόνων κλάσεών τους,

• αναφερθείτε σε επικαλυπτόµενες µεταβλητές της πρόγονης κλάσης κατά τη

συγγραφή των µεθόδων της απόγονης κλάσης,

• αναφέρετε πότε η Java εφαρµόζει την στατική διασύνδεση και πότε τη

δυναµική,

• περιγράψετε πώς η Java υποστηρίζει την πολλαπλή κληρονοµικότητα,

• ορίζετε interfaces και στη συνέχεια κλάσεις που τα υλοποιούν.

Page 109: Γλώσσες Προγραμματισμού II

ŒÓÓÔȘ ÎÏÂȉȿ

1 0 9H ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞ ™ ∆ ∏ J AVA

• extends

• abstract µέθοδος

• abstract κλάση

• super

• επικαλυπτόµενη µεταβλητή

• στατική διασύνδεση

• δυναµική διασύνδεση

• final

• interface

• implements

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Στις προηγούµενες ενότητες του κεφαλαίου αναφερθήκαµε στις βασικές έννοι-

ες της απλής κληρονοµικότητας, της πολλαπλής κληρονοµικότητας και του

πολυµορφισµού, καθώς και στον τρόπο µε τον οποίο η υιοθέτηση των εννοι-

ών αυτών επηρεάζει τη διαδικασία ανάπτυξης των προγραµµάτων. Η εξοι-

κείωση µε τις έννοιες αυτές αποτελεί ένα πολύ µεγάλο βήµα για την εφαρµο-

γή της αντικειµενοστρεφούς προσέγγισης στα συστήµατα που θα αναπτύσσε-

τε. Για το λόγο αυτό, αν δεν έχετε εµπεδώσει σε ικανοποιητικό βαθµό τις

προηγούµενες ενότητες θα σας συνιστούσα να επιµείνετε ακόµη µια φορά στις

έννοιες που αυτές εισάγουν, πριν περάσετε στην µελέτη της ενότητας αυτής.

Στην ενότητα αυτή, θα χρειαστεί να ανατρέξετε πάλι αργότερα, όταν στα πλαί-

σια της αντικειµενοστρεφούς εφαρµογής, που θα αναπτύξουµε στο κεφαλαίο

7, θα δείτε ότι η κληρονοµικότητα και ο πολυµορφισµός χρησιµοποιούνται

κατά κόρον στον ΑΠ. Επιπλέον, θα σας συνιστούσα µετά την ολοκλήρωση

της ενότητας, να ανατρέξετε στην ενότητα 7.18 του [Deitel 98] για ένα καλό

παράδειγµα κληρονοµικότητας και στο 7.19 του ίδιου βιβλίου για µια δια-

φορετική έκδοση του παραδείγµατός της 7.18 µε χρήση interface αντί για

abstract κλάσης.

6.4.1 √ÚÈÛÌfi˜ ·fiÁÔÓ˘ ÎÏ¿Û˘

Ας θυµηθούµε την κλάση Circle που ορίσαµε στο κεφάλαιο 3. Ένας τέτοι-

ος ορισµός είναι ίσως ικανοποιητικός για µαθηµατικούς χειρισµούς, δεν είναι

όµως αρκετός για χειρισµό κύκλων σ’ ένα γραφικό περιβάλλον, όπου η

εµφάνιση των κύκλων στην οθόνη είναι απαραίτητη. Για τον ορισµό της

συµπεριφοράς του κύκλου στο µήνυµα draw, που µια τέτοια απαίτηση προ-

ϋποθέτει, απαιτούνται πρόσθετες µεταβλητές όπως χρώµα περιγράµµατος,

χρώµα κύκλου, κ.λπ. Η νέα κλάση που προφανώς πρέπει να ορίσουµε θέλου-

Page 110: Γλώσσες Προγραμματισμού II

1 1 0 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

µε να έχει τα χαρακτηριστικά αυτά συν τα χαρακτηριστικά της κλάσης

Circle. Ονοµάζουµε τη νέα κλάση GraphicCircle και την ορίζουµε

εκµεταλλευόµενοι τον µηχανισµό της κληρονοµικότητας όπως παρακάτω:

public class GraphicCircle eexxtteennddss Circle

Color outline, fill; // Ë ÎÏ¿ÛË Color ·Ó··ÚÈÛÙ¿ ÙËÓ

// ¤ÓÓÔÈ· ¯ÚÒÌ· ηÈ

// Ú¤ÂÈ Ó· ÔÚÈÛı› ηٿÏÏËÏ·

public void draw()

// ÎÒ‰Èη˜ ÁÈ· ÙÔÓ Û¯ËÌ·ÙÈÛÌfi ÙÔ˘ ·ÎÏÔ˘ ΤÓÙÚÔ˘

// x,y Î·È ·ÎÙ›Ó·˜ r

Η λέξη κλειδί extends δηλώνει στο σύστηµα ότι η κλάση GraphicCircle

είναι απόγονος της Circle και κατά συνέπεια κληρονοµεί τις µεταβλητές

x, y και r τις οποίες και χρησιµοποιεί ο ορισµός της µεθόδου draw για να

ζωγραφίσει τον κύκλο. Η νέα κλάση κληρονοµεί και τις µεθόδους area και

circumference µε αποτέλεσµα, αν gc είναι ένα στιγµιότυπο της κλάσης

GraphicCircle, η πρόταση

double area = gc.area();

να υπολογίζει και να αναθέτει την επιφάνεια του στιγµιότυπου gc στην µετα-

βλητή area.

Ένα σηµαντικό χαρακτηριστικό της κληρονοµικότητας είναι ότι κάθε στιγ-

µιότυπο µιας απογόνου κλάσης µπορεί να θεωρηθεί στιγµιότυπο της προγό-

νου κλάσης. Έτσι, µπορούµε να αναθέσουµε το στιγµιότυπο gc σε µια ανα-

φορά Circle, όπως παρακάτω

Circle c = gc;

6.4.2 ∞ÊËÚË̤Ó˜ ÎÏ¿ÛÂȘ

Όταν ορίζουµε µια κλάση, συνήθως αναµένουµε να δηµιουργηθούν κατά το

χρόνο εκτέλεσης στιγµιότυπά της. Υπάρχουν όµως περιπτώσεις που είναι

βολικό να ορίσουµε µια κλάση, για την οποία εξ' αρχής είναι γνωστό, ότι δε

θα δηµιουργήσουµε στιγµιότυπα. Οι κλάσεις αυτές συναντώνται στα ανώ-

τερα επίπεδα των δένδρων κληρονοµικότητας και ονοµάζονται αφηρηµένες

Page 111: Γλώσσες Προγραμματισμού II

κλάσεις (abstract classes) σε αντίθεση µε τις κλάσεις που έχουν στιγµιότυ-

πα και ονοµάζονται πραγµατικές (concrete) κλάσεις.

Μια αφηρηµένη κλάση δηµιουργείται µε την προσδοκία ότι οι υποκλάσεις

της θα της προσθέσουν δοµή και συµπεριφορά, κάτι που συνήθως γίνεται

ορίζοντας το σώµα των λειτουργιών για τις οποίες ορίστηκε µόνο η διεπα-

φή. Στην Java αυτό γίνεται δηλώνοντας τη µέθοδο σαν abstract. Μία abstract

µέθοδος δεν έχει σώµα, απλά ορίζει την διεπαφή της λειτουργίας. Έτσι η

δήλωση της κλάσης Shape διαµορφώνεται όπως παρακάτω:

public class Shape

public abstract double area();

public abstract double circumference();

Το περιβάλλον υλοποίησης διασφαλίζει ότι δεν µπορούν να δηµιουργηθούν

στιγµιότυπα µιας κλάσης που διαθέτει έστω και µια abstract µέθοδο. Επι-

πλέον, κάθε abstract κλάση διαθέτει µια τουλάχιστο abstract µέθοδο. Η από-

γονος µιας abstract κλάσης δεν είναι και αυτή abstract, µόνο αν ορίζει τα

σώµατα όλων των abstract µεθόδων της.

1 1 1H ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞ ™ ∆ ∏ J AVA

Χρησιµοποιώντας τη σύνταξη της Java δώστε το δένδρο κληρονοµικότη-

τας των κλάσεων Circle, Shape, Cube, TwoDimensionalShape,

Rectangle, Sphere, ThreeDimensional–Shape. ∆ιακρίνατε τις

abstract από τις πραγµατικές κλάσεις.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘6.1

∆ώστε τον ορισµό των κλάσεων Circle και Rectangle εκµεταλλευόµε-

νοι τη δήλωση της κλάσης Shape που ήδη δώσαµε. Γράψτε ένα µικρό πρό-

γραµµα για να ελέγξετε συντακτικά τον κώδικά σας.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘6.2

6.4.3 ∫¿ı ÎÏ¿ÛË ¤¯ÂÈ ÌÈ· ÚfiÁÔÓÔ ÎÏ¿ÛË

Στην Java κάθε κλάση που ορίζει ο χρήστης έχει µια πρόγονο κλάση. Η κλάση

αυτή είτε ορίζεται άµεσα από το χρήστη µε τη χρήση του extends, είτε ορί-

Page 112: Γλώσσες Προγραμματισμού II

1 1 2 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

ζεται έµµεσα από το σύστηµα, σε περίπτωση που στον ορισµό της δεν χρη-

σιµοποιείται το extends. Στη δεύτερη αυτή περίπτωση, η κλάση πρόγονος

είναι η κλάση Object του συστήµατος. Η κλάση Object, που είναι η µόνη

κλάση που δεν έχει πρόγονο, ορίζει ένα σύνολο από µεθόδους, τις οποίες κάθε

στιγµιότυπο της Java µπορεί να χρησιµοποιήσει. Το σχήµα 6.6 δίνει ένα µικρό

µέρος από το διάγραµµα ιεραρχίας κλάσεων της Java, όπως διαµορφώθηκε

µε τις δηλώσεις των κλάσεων Circle και GraphicCircle

Object Circle:

Numder:

System:

String:

Math:

Component

:

Double:

Float:

Integer:

Long:

Container:

Button:

List

Panel Applet

GraphicCircle

™¯‹Ì· 6.6

Ιεραρχία κλάσεων µε τις

κλάσεις Circle και

GraphicCircle.

∆ώστε για την κλάση GraphicCircle τον ορισµό ενός δηµιουργού, που

θα αναθέτει τις κατάλληλες τιµές σε όλες τις µεταβλητές στιγµιότυπου της

κλάσης.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

6.3

6.4.4 √È ‰ËÌÈÔ˘ÚÁÔ› ÛÙËÓ ÎÏËÚÔÓÔÌÈÎfiÙËÙ·

∆ηµιουργοί κλάσεων απογόνων

Αν εξετάσετε τον κώδικα του δηµιουργού που δώσατε στην άσκηση Αυτο-

αξιολόγησης 3 θα διαπιστώσετε πως επαναλαµβάνει τον κώδικα του δηµι-

ουργού της κλάσης Circle και στη συνέχεια παραθέτει την αρχικοποίηση

των επιπλέον µεταβλητών. Η επανάληψη αυτή θα ήταν πιο εµφανής, εάν ο

δηµιουργός της Circle περιελάµβανε ένα µεγάλο αριθµό προτάσεων. Για

την αποφυγή αυτής της επανάληψης, η Java διαθέτει τη δεσµευµένη λέξη

super η οποία µας επιτρέπει να καλέσουµε το δηµιουργό της προγόνου κλά-

σης. Έτσι, ο δηµιουργός διαµορφώνεται όπως στο σχήµα 6.7.

Page 113: Γλώσσες Προγραμματισμού II

public GraphicCircle(double x, double y, double r, Color

outline, Color fill)

ssuuppeerr(( xx,, yy,, rr ));;

this.outline = outline;

this.fill = fill;

∆ύο περιορισµοί διέπουν τη χρήση του super µε τη σηµασία που αναφέρθη-

κε παραπάνω. Πρώτον, µπορεί να χρησιµοποιηθεί µόνο µέσα στο σώµα ενός

δηµιουργού και δεύτερον, πρέπει να αποτελεί την πρώτη πρόταση πριν

ακόµη και από τις δηλώσεις των µεταβλητών.

1 1 3H ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞ ™ ∆ ∏ J AVA

™¯‹Ì· 6.7

∆ηµιουργός της κλάσης

GraphicCircle.

Περιγράψτε τη σηµασία προτάσεων της µορφής this (…) και super (…)

στο σώµα ενός δηµιουργού.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘6.4

Αναφέρατε τους δηµιουργούς και τη σειρά µε την οποία εκτελούνται κατά

την δηµιουργία ενός στιγµιότυπου της κλάσης GraphicCircle µε κλήση

του δηµιουργού που δίνεται στο σχήµα 6.7.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘6.5

Αλυσιδωτή κλήση δηµιουργών

Για κάθε κλάση που ορίζετε, η Java διασφαλίζει ότι ο δηµιουργός της καλεί-

ται κάθε φορά που ένα στιγµιότυπο της κλάσης δηµιουργείται. ∆ιασφαλίζει

επίσης ότι ο δηµιουργός καλείται και όταν δηµιουργούνται στιγµιότυπα των

κλάσεων απογόνων. Έτσι, αν η πρώτη πρόταση ενός δηµιουργού δεν περιέ-

χει µια άµεση κλήση του δηµιουργού του προγόνου του µε το super, η Java

έµµεσα εισάγει µια κλήση της µορφής super (). Επειδή µια τέτοια κλήση

δεν έχει παραµέτρους, το σύστηµα παράγει ένα λάθος µεταγλώττισης, εάν η

πρόγονος κλάση δεν διαθέτει δηµιουργό χωρίς παραµέτρους.

Η κλήση της super () δεν εισάγεται στην περίπτωση που η πρώτη πρόταση

του δηµιουργού είναι κλήση άλλου δηµιουργού µε τη σύνταξη this (). Τελι-

κά όµως, σε κάθε περίπτωση ο τελευταίος δηµιουργός θα καλέσει το δηµι-

ουργό της προγόνου κλάσης.

Page 114: Γλώσσες Προγραμματισμού II

1 1 4 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

6.4.5 ∂ÈÎ·Ï˘ÙfiÌÂÓ˜ ÌÂÙ·‚ÏËÙ¤˜

Υποθέστε τώρα, ότι η κλάση µας GraphicCircle έχει µια νέα µεταβλητή

για την αναπαράσταση της ανάλυσης (resolution) σύµφωνα µε την οποία θα

εµφανισθεί στην οθόνη ο κύκλος. Υποθέτοντας σαν όνοµα το r, η δήλωση

της GraphicCircle διαµορφώνεται όπως παρακάτω:

public class GraphicCircle extends Circle

Color outline, fill; // Ë ÎÏ¿ÛË Color ·Ó··ÚÈÛÙ¿ ÙËÓ

// ¤ÓÓÔÈ· ¯ÚÒÌ· ηÈ

// Ú¤ÂÈ Ó· ÔÚÈÛı› ηٿÏÏËÏ·

float r; // resolution in dot–per–inch.

public GraphicCircle(double x, double y, double radius,

Color outline, Color fill)

super( x, y, radius ); this.outline = outline;

this.fill = fill;

public void setResolution(float resolution)

r =resolution;

public void draw()

// ÎÒ‰Èη˜ ÁÈ· ÙÔÓ Û¯ËÌ·ÙÈÛÌfi ÙÔ˘ ·ÎÏÔ˘ ΤÓÙÚÔ˘

// x,y Î·È ·ÎÙ›Ó·˜ r

Παρατηρώντας το σώµα της µεθόδου setResolution είναι προφανές ότι το

όνοµα r δεν αναφέρεται πλέον στην ακτίνα του κύκλου. Η µεταβλητή r που

αναπαριστά την ανάλυση επικαλύπτει (shadows) τη µεταβλητή r που ανα-

παριστά την ακτίνα στην πρόγονο κλάση Circle. Μπορούµε να αναφερ-

θούµε στην επικαλυπτόµενη µεταβλητή της προγόνου κλάσης χρησιµοποι-

ώντας τη λέξη κλειδί super. Έτσι η έκφραση

ssuuppeerr..rr

αναφέρεται στη µεταβλητή r της προγόνου κλάσης Circle η οποία αναπα-

ριστά την ακτίνα του κύκλου. H σύνταξη αυτή δεν επιτρέπει αναφορά σε επι-

καλυπτόµενη µεταβλητή που ορίζεται σε κλάση που δεν είναι πρώτου βαθ-

µού πρόγονος. Μια τέτοια αναφορά µπορεί να γίνει µόνο µε την έκφραση

((((CCiirrccllee))tthhiiss))..rr

Page 115: Γλώσσες Προγραμματισμού II

η οποία περιλαµβάνει άµεση µετατροπή (cast) της αναφοράς this στην κατάλ-

ληλη πρόγονο κλάση, και στη συνέχεια αναφορά στη µεταβλητή.

1 1 5H ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞ ™ ∆ ∏ J AVA

Αν η κλάση M είναι απόγονος της L, η οποία µε τη σειρά της είναι απόγο-

νος της K, και η κλάση Μ επικαλύπτει την µεταβλητή x, η οποία ορίζεται

επίσης στις κλάσεις K και L, κάντε τις σωστές αντιστοιχήσεις, για τις παρα-

κάτω εκφράσεις του εσωτερικού της Μ:

έκφραση σηµασία

this.x µεταβλητή x της κλάσης K

x µεταβλητή x της κλάσης L

super.x µεταβλητή x της κλάσης M

((L)this).x η έκφραση δεν έχει νόηµα

super.super.x

((K)this).x

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘6.6

6.4.6 ÀÂÚÎ¿Ï˘„Ë ÌÂıfi‰ˆÓ

Μετά τη µελέτη της επικάλυψης των µεταβλητών λογικό είναι να περιµένε-

τε µια ανάλογη συµπεριφορά και από τις µεθόδους. Πράγµατι, µια µέθοδος

µιας κλάσης επικαλύπτει µια µέθοδο προγόνου κλάσης της, η οποία έχει το

ίδιο όνοµα και τα ίδια ορίσµατα, αλλά αυτό συµβαίνει µε διαφορετικό τρόπο

και γι’ αυτό και ονοµάζεται υπερκάλυψη (overriding). Και ενώ υπάρχει δυνα-

τότητα αναφοράς στην επικαλυπτόµενη µεταβλητή, κάτι τέτοιο δεν είναι

δυνατό για την υπερκαλυπτόµενη µέθοδο. Έτσι, αν θεωρήσουµε πως η κλάση

Circle υπερκαλύπτει τη µέθοδο area της κλάσης Ellipse και c είναι ανα-

φορά σε στιγµιότυπο της κλάσης Circle τότε η έκφραση

((((EElllliippssee))cc))..aarreeaa(())

δεν αναφέρεται στη µέθοδο area της κλάσης Ellipse, αλλά της κλάσης

Circle. Στην συµπεριφορά αυτή εξάλλου βασίζεται και ο πολυµορφισµός

στον οποίο ήδη αναφερθήκαµε.

Page 116: Γλώσσες Προγραμματισμού II

1 1 6 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

™Ù·ÙÈ΋ ‹ ‰˘Ó·ÌÈ΋ ‰È·Û‡Ó‰ÂÛË;

Όπως ήδη αναφέραµε οι αντικειµενοστρεφείς γλώσσες εφαρµόζουν επιλε-

κτικά τη στατική και δυναµική διασύνδεση. Η Java εφαρµόζει στατική δια-

σύνδεση στις static µεθόδους, καθώς αυτές δεν µπορεί να υπερκαλυφθούν.

Το ίδιο συµβαίνει και µε τις private µεθόδους, οι οποίες καθώς δεν κλη-

ρονοµούνται από τις απογόνους κλάσεις δεν µπορούν να υπερκαλυφθούν.

Τέλος οι final µέθοδοι, καθώς και οι µέθοδοι των final κλάσεων καλούνται

και αυτές άµεσα. Επιπλέον, ο µεταγλωττιστής στις περιπτώσεις αυτές και

ανάλογα µε το µέγεθος της κάθε µεθόδου εφαρµόζει επιλεκτικά την τεχνική

της ενσωµάτωσης του κώδικα (inlining) για βελτίωση των επιδόσεων.

∆ώστε το αποτέλεσµα της εκτέλεσης του παρακάτω κώδικα:

class K

int x = 1;

int res() return x;

class M extends K

int x = 2;

int res() return –x;

public class override_test

public static void main(String args[])

M m = new M();

System.out.println(m.x);

System.out.println(m.res());

K k = (K)m;

System.out.println(k.x);

System.out.println(k.res());

Αιτιολογήστε την απάντησή σας. Στη συνέχεια αναπτύξτε ένα πρόγραµµα

για να ελέγξετε τα αποτελέσµατά σας.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

6.7

Page 117: Γλώσσες Προγραμματισμού II

Κλήση υπερκαλυπτόµενης µεθόδου

Θεωρούµε τον παρακάτω κώδικα:

class K

int x = 1;

int func() return x;

class L extends K

int x; // ÂÈηχÙÂÈ ÙËÓ x

// Ù˘ ∫

int func() // ˘ÂÚηχÙÂÈ ÙËÓ

// func Ù˘ K

x = 2 * super.x; // ·Ó·Ê¤ÚÂÙ·È ÛÙËÓ x

// Ù˘ ∫

return super.func() + x; // ηÏ› ÙËÓ func Ù˘ K

Σηµειώστε την έκφραση super.func[2], αναφέρεται στην µέθοδο func της προ-

γόνου κλάσης, όπως ακριβώς και η έκφραση super.x για την αντίστοιχη

µεταβλητή. Παρ’ότι όµως η έκφραση super.x είναι ισοδύναµη µε την

((∫)this).x, δεν συµβαίνει το ίδιο και για την super.func() που δεν

είναι ισοδύναµη της ((K)this).func(). Πιο συγκεκριµένα, στη µεν

έκφραση ((K)this).func() έχουµε late binding στη δε super.func()

έχουµε early binding. O µεταγλωττιστής καλεί άµεσα τη µέθοδο που η πρό-

γονος κλάση ορίζει.

Στο κεφάλαιο 7 του [Deitel 98] µπορείτε να βρείτε κάτω από τον τίτλο «7.13

Case Study: Inheriting Interface and Implementation» ένα εκτεταµένο και

καλό παράδειγµα κληρονοµικότητας διεπαφής και υλοποίησης µε τις γνω-

στές µας κλάσεις Shape, Circle, κ.λπ.

1 1 7H ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞ ™ ∆ ∏ J AVA

[2] H έκφραση αυτή έχει νόηµα µόνο µέσα στο σώµα της απογόνου κλάσης.

Page 118: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞1 1 8

Στον παρακάτω κώδικα αντιστοιχήστε τις προτάσεις που περιέχουν εκφράσεις σε bold µε το σχόλιο

που τους αρµόζει από τη δεξιά στήλη. Στη συνέχεια, αναπτύξτε ένα πρόγραµµα και ελέγξτε τα απο-

τελέσµατά σας.

class K

int i = 1;

int func() return i;

class ª extends K

iinntt ii==33;;

iinntt ffuunncc(())

i = 2 * ssuuppeerr..ii;;

return ssuuppeerr..ffuunncc(()) + i;;

void func2()

System.out.println(ssuuppeerr..ffuunncc(()));;

System.out.println(((((KK))tthhiiss))..ffuunncc(()));;

public class Test1

public static void main(String[] args)

M m = new M();

System.out.println(mm..ii);

System.out.println(((((KK))mm))..ii);

System.out.println( ((((KK))mm))..ffuunncc(()) );

System.out.println( mm..ffuunncc(()) );

m.func2();

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

6.8

// υπερκαλύπτει την func της K

// επικαλύπτει την i της Κ

// καλεί την func της Κ

// καλεί την func της Μ

// αναφέρεται στην i της Μ

// αναφέρεται στην i της Κ

Page 119: Γλώσσες Προγραμματισμού II

6.4.7 Interfaces

Η κλάση, όπως ήδη αναφέραµε, αποτελεί το µηχανισµό της γλώσσας για την

υλοποίηση της ενθυλάκωσης. Επιτρέπει στις δηλώσεις των λειτουργιών τις

οποίες προσφέρει να είναι ορατές από το εξωτερικό περιβάλλον της, ενώ

αποκρύπτει τις υλοποιήσεις τους και τα δεδοµένα της. Ένας καλύτερος δια-

χωρισµός του τρόπου επικοινωνίας από την υλοποίηση παρέχεται από την

κατασκευή της abstract κλάσης. Σύµφωνα µ’ αυτή συγκεντρώνουµε σε µια

κλάση µόνο αφηρηµένες µεθόδους και ορίζουµε τις υλοποιήσεις των µεθό-

δων αυτών στις απογόνους κλάσεις της.

Μια εναλλακτική και πιο ευέλικτη τεχνική είναι ο πλήρης διαχωρισµός της

διεπαφής, του τρόπου δηλαδή επικοινωνίας, από την υλοποίηση. Η τάση

αυτή κερδίζει συνεχώς έδαφος αποτελώντας βασική αρχή του προγραµµα-

τισµού του βασισµένου σε components (component based development).

Σύµφωνα µ’ αυτή, χρησιµοποιείται µια ειδική γλώσσα[3] για να περιγράψει

τις διεπαφές των components διασφαλίζοντας την µεταξύ τους επικοινωνία.

Σ’ ένα επόµενο βήµα αναπτύσσονται (υλοποιούνται) τα components χρησι-

µοποιώντας οποιαδήποτε γλώσσα προγραµµατισµού, χωρίς αυτό να επηρε-

άζει την µεταξύ τους επικοινωνία.

Στα πλαίσια µιας ανάλογης λογικής, η Java χρησιµοποιεί την κατασκευή του

interface για τον ορισµό της διεπαφής και στη συνέχεια σ’ ένα επόµενο βήµα

ορίζονται µια ή περισσότερες κλάσεις που υλοποιούν (implement) τη διεπαφή.

Βασική διαφορά των interfaces από τις abstract κλάσεις είναι ότι τα interfaces

ορίζονται έξω από την ιεραρχία κληρονοµικότητας. Κάθε κλάση µπορεί να

υλοποιεί ένα interface ανεξάρτητα από την θέση της στην ιεραρχία, όπως

αυτό φαίνεται στο σχήµα 6.7. Μετά τη δήλωση του interface είναι δυνατή η

δήλωση µεταβλητής του συγκεκριµένου τύπου interface και η ανάθεση σ’

αυτή στιγµιότυπου οποιασδήποτε από τις κλάσεις που υλοποιεί το interface.

Λέµε ότι το στιγµιότυπο είναι σύµφωνο (conforms) µε το interface ή µε τον

τύπο που αυτό αναπαριστά. Το γεγονός αυτό µας δίνει την δυνατότητα να

χειριστούµε ενιαία στιγµιότυπα κλάσεων που βρίσκονται σε διαφορετικά επί-

πεδα, αλλά και δένδρα ιεραρχίας προσφέροντας µεγάλη ευελιξία στη διαδι-

κασία ανάπτυξης.

1 1 9H ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞ ™ ∆ ∏ J AVA

[3] Γνωστή µε το όνοµα Interface Definition Language (IDL).

Page 120: Γλώσσες Προγραμματισμού II

1 2 0 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

Επιπλέον, µια κλάση µπορεί να υλοποιεί διάφορες διεπαφές και έτσι τα στιγ-

µιότυπά της µπορούν να χρησιµοποιηθούν οπουδήποτε ορίζεται µια σύµ-

φωνου τύπου διεπαφή. Η συγγραφή του κώδικα των αντικειµένων–πελάτη

γίνεται µε τη χρήση της διεπαφής και η µόνη προϋπόθεση για να χρησιµο-

ποιηθούν τα στιγµιότυπα µιας κλάσης απ’ αυτόν τον κώδικα είναι η κλάση

να υλοποιεί τη διεπαφή. Εάν αντίθετα είχε χρησιµοποιηθεί για τη συγγραφή

του κώδικα µια κλάση Α, τότε µόνο στιγµιότυπα της κλάσης Α και των απο-

γόνων της θα µπορούσαν να χρησιµοποιηθούν. Αυτό θα µας ανάγκαζε να

κάνουµε απόγονο της Α κάθε κλάση της οποίας στιγµιότυπα θα θέλαµε να

χρησιµοποιήσουµε, ανεξάρτητα από το ποιά πραγµατικά θα έπρεπε να είναι

η πρόγονος της νέας κλάσης.

Ένα ακόµη σηµαντικό στοιχείο των interfaces είναι η δυνατότητά τους να

υποστηρίξουν σε κάποιο βαθµό την πολλαπλή κληρονοµικότητα. H Java

όπως είδαµε δεν υποστηρίζει πολλαπλή κληρονοµικότητα όπως κάνει για

παράδειγµα η C++ και η CLOS και σε µικρότερο βαθµό η Smalltalk, αλλά

ο µηχανισµός των interfaces επιτρέπει στην Java να εκµεταλλευθεί ορισµέ-

να από τα πλεονεκτήµατα του πολυµορφισµού, αποφεύγοντας ταυτόχρονα

προβλήµατα για τα οποία η πολλαπλή κληρονοµικότητα κατακρίνεται.

∆ήλωση Interface

Η δήλωση ενός interface αποτελείται από το όνοµα του τύπου που προσδιο-

ρίζει, ένα σύνολο δηλώσεων abstract µεθόδων και προαιρετικά από ένα σύνο-

λο δηλώσεων σταθερών. Ο παρακάτω κώδικας δηλώνει το interface

Drawable:

public interface Drawable

public void setColor(Color c);

public void setPosition(double x, double y);

object

Kλάση

∆ιεπαφή

inherits

implements

™¯‹Ì· 6.7

Κλάσεις και interfaces.

Page 121: Γλώσσες Προγραμματισμού II

public void draw(DrawWindow dw);

Το interface σε αντίθεση µε την abstract κλάση περιέχει µόνο αφηρηµένες

µεθόδους. ∆εν µπορεί επιπλέον να περιέχει µεταβλητές παρά µόνο static και

final, δηλαδή σταθερές. Τα interfaces δηλώνονται µέσα στα αρχεία πηγαί-

ου κώδικα, όπως οι κλάσεις. Εάν η διεπαφή δηλωθεί public, είναι ορατή

από κλάσεις άλλων πακέτων, µε τον περιορισµό βέβαια ότι σε κάθε αρχείο

µπορεί να υπάρχει µόνο µια public διεπαφή ή κλάση. Εάν η διεπαφή δεν

είναι public, είναι ορατή µόνο στο πακέτο που ορίζεται. Την ίδια ορατότητα

µε την διεπαφή έχουν και όλες οι µέθοδοι και οι σταθερές που η διεπαφή ορί-

ζει. Μια διεπαφή µπορεί να επεκτείνει ή κληρονοµεί µια ή περισσότερες

άλλες διαπαφές, όπως φαίνεται στον παρακάτω κώδικα:

interface D extends A, B, C

// ‰ËÏÒÛÂȘ ÌÂıfi‰ˆÓ Î·È ÛÙ·ıÂÚÒÓ

Όλες οι µέθοδοι και οι σταθερές των διεπαφών Α, Β και C κληρονοµούνται

από την διεπαφή D, αλλά καθεµιά µπορεί να δηλωθεί εκ νέου αποκρύπτο-

ντας το κληρονοµούµενο στοιχείο. Για την αναφορά σε σταθερές πρόγονων

διεπαφών, η σύνταξη της µορφής Α.<όνοµα σταθεράς> διευκολύνει την ανα-

φορά σε σταθερές που έχουν το ίδιο όνοµα σε δύο ή περισσότερες διεπαφές

προγόνους.

Επιπλέον, µια διεπαφή µπορεί να ενσωµατωθεί µέσα σε µια κλάση, οπότε

και θεωρείται σαν static, αλλά και µέσα σε άλλη διεπαφή, αν κάτι τέτοιο έχει

κάποιο νόηµα.

Υλοποίηση Interface

Χρησιµοποιούµε τη λέξη κλειδί implements για να δηλώσουµε ότι µια

κλάση υλοποιεί ένα ή περισσότερα interfaces. Αυτό δεν περιορίζει τη δυνα-

τότητα της κλάσης να κληρονοµήσει µια άλλη κλάση. Οι µεταβλητές των

interfaces γίνονται static µεταβλητές της κλάσης. Αν δε η κλάση δεν ορί-

ζει τα σώµατα όλων των µεθόδων του interface, τότε αυτή πρέπει να δηλω-

θεί σαν abstract.

Σαν παράδειγµα, δίνεται παρακάτω η δήλωση της κλάσης Drawable

Circle, η οποία κληρονοµεί (extends) την κλάση Circle και ταυτόχρο-

1 2 1H ∫ § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞ ™ ∆ ∏ J AVA

Page 122: Γλώσσες Προγραμματισμού II

1 2 2 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

να υλοποιεί (implements) το interface Drawable.

public class DrawableCircle extends Circle implements

Drawable

private Color c;

public DrawableCircle(double x, double y, double r)

super(x,y,r);

public void setColor(Color c) this.c = c;

public void setPosition(double x, double y) super.x

= x; super.y = y;

Οι ορισµοί των interfaces δηµιουργούν ονόµατα τύπων όπως ακριβώς κάνουν

και οι ορισµοί κλάσης. Αν χρησιµοποιήσετε το όνοµα ενός interface σαν

όνοµα τύπου µιας µεταβλητής, οποιοδήποτε αντικείµενο υλοποιεί αυτό το

interface µπορεί να ανατίθεται σ’ αυτή τη µεταβλητή. Έτσι, τα στιγµιότυπα

της DrawableCircle είναι σύµφωνα µε τους τύπους Circle και

Drawable και εποµένως µπορούν να µπούνε οπουδήποτε απαιτείται µια

αναφορά των δύο αυτών τύπων όπως φαίνεται στο σχήµα 6.8.

Shapes[] shapes = new Shapes[10];

Drawable[] drawables = new Drawable[10];

DrawableCircle dc1 = new DrawableCircle(2,3,1);

DrawableRectangle dr = new DrawableRectangle(2.0,4.0);

DrawableCircle dc2 = new DrawableCircle(2,3,1);

shapes[0] = dc1; shapes[1] = dr; shapes[2] = dc2;

drawable[0] = dc1; drawable[1] = dr; drawable[2] = dc2;

double area = 0;

for(int i=0;i<shapes.length;i++)

area += shapes[i].area();

drawables[i].draw(dw);

™¯‹Ì· 6.8

Μετατρέποντας στιγµιότυπα στους τύπους των διεπαφών που υλοποιούν.

Page 123: Γλώσσες Προγραμματισμού II

™‡ÓÔ„Ë ÂÓfiÙËÙ·˜

Στην ενότητα αυτή είδαµε τον τρόπο µε τον οποίο χρησιµοποιούµε τις δια-

θέσιµες κλάσεις για τον ορισµό των νέων κλάσεων που απαιτούν οι εκάστο-

τε εφαρµογές µας. Εκµεταλλευόµενοι την απλή κληρονοµικότητα έχετε την

δυνατότητα να ορίσετε πολύ εύκολα σύνθετες κλάσεις, οι οποίες θα κληρο-

νοµούν το µεγαλύτερο µέρος της συµπεριφοράς τους από υπάρχουσες κλά-

σεις, µε µόνη απαίτηση από σας να ορίσετε την νέα ή τροποποιηµένη συµπε-

ριφορά των νέων κλάσεων. Προς αυτή την κατεύθυνση έχετε στη διάθεση σας

τις παρακάτω λέξεις κλειδιά της Java:

extends: Xρησιµοποιείται στη δήλωση µιας κλάσης για να κληρονοµήσει αυτή

αναπαράσταση και συµπεριφορά από άλλη διαθέσιµη κλάση. Ανάλογη χρήση

έχει και µε τα interfaces.

abstract: Xρησιµοποιείται στη δήλωση µεθόδου για να ορίσει πως η κλάση

ορίζει µόνο τη διεπαφή της µεθόδου και αφήνει για τις απογόνους της τον

ορισµό της υλοποίησής της.

super: Xρησιµοποιείται στον κώδικα των µεθόδων απόγονης κλάσης για

άµεση αναφορά των αντίστοιχων υπερκαλυπτόµενων µεθόδων και επικαλυ-

πτόµενων µεταβλητών της πρόγονης κλάσης.

interface: Xρησιµοποιείται για τη δηµιουργία κατασκευών διεπαφής.

implements: Xρησιµοποιείται στη δήλωση µιας κλάσης για να ορίσει ότι η

κλάση υλοποιεί συγκεκριµένη διεπαφή ή διεπαφές. Η κλάση στην περίπτωση

αυτή ορίζει τις υλοποιήσεις των µεθόδων, των interfaces που implements.

1 2 3™ Y N O æ H E N O T H TA ™

Θεωρήστε το πακέτο (package) P το οποίο περιλαµβάνει ένα σύνολο κλά-

σεων. Αν οι κλάσεις αυτές χρησιµοποιούν ένα σηµαντικό αριθµό κοινών

σταθερών, πώς θα προχωρήσετε στη δήλωση αυτών των σταθερών;

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘6.9

Χρησιµοποιήστε την κατασκευή της διεπαφής για να δηλώσετε τις κλάσεις

Circle και Rectangle µε τρόπο ώστε τα στιγµιότυπά τους να µπορούν

να χρησιµοποιηθούν πολυµορφικά όσον αφορά τις λειτουργίες area και

circumference. ∆ώστε ένα τµήµα κώδικα στο οποίο θα επιδεικνύετε το

χαρακτηριστικό αυτό.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘6.10

Page 124: Γλώσσες Προγραμματισμού II

1 2 4 ∫ ∂ º ∞ § ∞ π √ 6 : K § ∏ ƒ √ ¡ √ ª π ∫ √ ∆ ∏ ∆∞

Επιπλέον, είδαµε πως ο ορισµός αφηρηµένων κλάσεων µας βοηθά στην

εφαρµογή του πολυµορφισµού, µε όλα τα θετικά αποτελέσµατα που αυτός

συνεπάγεται για µία εφαρµογή, και πως ο µηχανισµός του interface µπορεί

να χρησιµοποιηθεί για να πετύχουµε από την Java την εν µέρει υποστήριξη

της πολλαπλής κληρονοµικότητας.

™‡ÓÔ„Ë

Στο κεφάλαιο αυτό αναφερθήκαµε στο µηχανισµό της κληρονοµικότητας και

στο χαρακτηριστικό του πολυµορφισµού. Κληρονοµικότητα και πολυµορφι-

σµός διακρίνουν τον αντικειµενοστρεφή από το βασισµένο σε αντικείµενα

(object–based) προγραµµατισµό.

Η κληρονοµικότητα αποτελεί µια µορφή επαναχρησιµοποίησης λογισµικού σύµ-

φωνα µε την οποία νέες κλάσεις δηµιουργούνται αφοµοιώνοντας και προσαρ-

µόζοντας στις απαιτήσεις τους µεταβλητές και συµπεριφορά δοκιµασµένων και

υψηλής ποιότητας διαθέσιµων κλάσεων. Η δηµιουργούµενη κλάση, υποκλάση

όπως ονοµάζεται, κληρονοµεί ή επεκτείνει (extends) µια υπάρχουσα κλάση που

καλείται υπερκλάση. Η υποκλάση κληρονοµεί όλες τις µεταβλητές και µεθό-

δους της υπερκλάσης που είναι ορατές από αυτή και επιπλέον µπορεί είτε να

προσθέσει νέες µεταβλητές και µεθόδους είτε να υπερκαλύψει υπάρχουσες.

Όταν ορίζουµε µια νέα υποκλάση κληρονοµώντας χαρακτηριστικά από δύο

ή περισσότερες υπερκλάσεις λέµε ότι έχουµε πολλαπλή κληρονοµικότητα. Το

είδος αυτό της κληρονοµικότητας αν και αυξάνει το βαθµό επαναχρησιµο-

ποίησης αποτελεί πηγή δηµιουργίας προβληµάτων και δεν υποστηρίζεται από

όλα τα περιβάλλοντα υλοποίησης. Η Java σε µια προσπάθεια αποφυγής των

προβληµάτων που εισάγει η πολλαπλή κληρονοµικότητα την υποστηρίζει

έµµεσα διαµέσου του µηχανισµού του interface.

Σύµφωνα µε τον πολυµορφισµό τα στιγµιότυπα ενός συνόλου κλάσεων που

είναι συµβατές µε µια κληρονοµούµενη κοινή διεπαφή µπορούν να θεωρη-

θούν στιγµιότυπα της υπερκλάσης και να αντιµετωπισθούν σαν οµοειδή,

παραβλέποντας τις επί µέρους διαφοροποιήσεις τους. Ο πολυµορφισµός µας

επιτρέπει να σχεδιάζουµε προγράµµατα που είναι ικανά να χειριστούν µε ευε-

λιξία ποικιλίες υπαρκτών κλάσεων αλλά και συγγενικών κλάσεων που θα ορι-

σθούν σε επόµενα βήµατα, διευκολύνοντας µε τον τρόπο αυτό την επεκτασι-

µότητα του λογισµικού. Νέες κλάσεις µπορούν να προστεθούν στο σύστηµα

χωρίς να χρειασθεί να τροποποιήσουµε τις ήδη υπάρχουσες.

Page 125: Γλώσσες Προγραμματισμού II

BÈ‚ÏÈÔÁÚ·Ê›·

[1] [Booch 94]

Gr.ady Booch, «Object–Oriented Analysis and Design with

applications» second edition, Benjamin/Cummings Publishing

Company Inc. 1994.

[2] [Jacobson 92]

Ivar Jacobson, «Object–Oriented Software Engineering – A use case

Driven Approach», Addison–Wesley 1992.

[3] [Rumbaugh 91]

J. Rumbaugh, et.al «Object–Oriented Modeling and Design» Prentice

Hall International 1991.

[4] [Deitel 98]

Deitel & Deitel «Java: How to program», Second edition, Prentice Hall

International 1998.

Το βιβλίο αυτό είναι ένα από τα καλύτερα κείµενα για την Java, εισά-

γοντας ταυτόχρονα και τις βασικές έννοιες του Αντικειµενοστρεφούς

προγραµµατισµού αλλά και γενικότερα προγραµµατισµού υπολογιστών.

Αν και δεν προϋποθέτει εµπειρία σε προγραµµατισµό και εποµένως µπο-

ρεί να χρησιµοποιηθεί από αρχάριους σε προγραµµατισµό, µπορεί ταυ-

τόχρονα να χρησιµοποιηθεί και από καλούς προγραµµατιστές C και C++

για εκµάθηση της Java. Το βιβλίο είναι κατάλληλο και για επαγγελµα-

τίες προγραµµατιστές, καθώς αφιερώνει ένα µεγάλο µέρος του στην

βιβλιοθήκη κλάσεων της γλώσσας δίνοντας πολλά και καλά παραδείγ-

µατα χρήσης της.

1 2 5B I B § I O ° PA º I A

Page 126: Γλώσσες Προγραμματισμού II
Page 127: Γλώσσες Προγραμματισμού II

AÓ¿Ù˘ÍË AÓÙÈÎÂÈÌÂÓÔÛÙÚÂÊÔ‡˜ EÊ·ÚÌÔÁ‹˜

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να παρουσιάσει τη διαδικασία ανάπτυξης µιας

πραγµατικής αντικειµενοστρεφούς εφαρµογής χρησιµοποιώντας τη γνώση

που αποκτήθηκε από τα προηγούµενα κεφάλαια.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• αντιµετωπίσετε µε µεγαλύτερη οικειότητα την ανάπτυξη µιας πραγµατικής

εφαρµογής, χρησιµοποιώντας τις έννοιες που εισήχθησαν στα προηγούµε-

να κεφάλαια,

• εφαρµόσετε την τεχνική της αυξητικής ανάπτυξης στη διαδικασία ανάπτυξης.

ŒÓÓÔȘ ÎÏÂȉȿ

7∫ ∂ º ∞ § ∞ π √

• incremental development

• σύζευξη (coupling)

• problem space

• solution space

• object collaboration

• CRC

• Responsibilities

∏ ∂Ê·ÚÌÔÁ‹

Να κατασκευαστεί πρόγραµµα σε Java που να ακολουθεί την αντίστροφη

Πολωνική σηµειογραφία και να εκτελεί τις τέσσερεις βασικές αριθµητικές

πράξεις.

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Πρόκειται για την ανάπτυξη µιας εφαρµογής που συναντήσατε ήδη στη Θεµα-

τική Ενότητα 3.4. Η επιλογή αυτή έγινε για να σας δώσει τη δυνατότητα αντι-

παράθεσης του αντικειµενοστρεφούς παραδείγµατος µε το κλασικό διαδικα-

στικό παράδειγµα, µε το οποίο η εφαρµογή αντιµετωπίσθηκε στην ΘΕ 3.4.

Θα χρησιµοποιήσουµε την τεχνική της αυξητικής ανάπτυξης (incremental

development). Σύµφωνα µε την τεχνική αυτή αναπτύσσουµε το πρόγραµµα

Page 128: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 7 : A ¡ ∞ ¶ ∆ À • ∏ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ E º ∞ ƒ ª √ ° ∏ ™1 2 8

σε διαδοχικά βήµατα όπου στο κάθε βήµα ορίζουµε περιορισµένο αριθµό κλά-

σεων, ελέγχουµε την ορθότητα κάθε νέας κλάσης και ενσωµατώνουµε τις νέες

κλάσεις στον κώδικα του προηγούµενου βήµατος.

Θα παρακολουθήσουµε την ανάπτυξη του προγράµµατος σε ορισµένα αρχι-

κά βήµατα. Στα πρώτα αυτά βήµατα θα αγνοήσουµε πλήρως τον τρόπο µε

τον οποίο επικοινωνεί ο χρήστης µε το σύστηµα. Η επικοινωνία αυτή θα µπο-

ρεί να γίνεται διαµέσου της γραµµής διαταγών, ή ακόµη καλύτερα διαµέσου

ενός γραφικού περιβάλλοντος όπως αυτού του calculator των MS Windows.

Ίσως, σε λίγα χρόνια, η τεχνολογία µας δώσει τη δυνατότητα να έχουµε σαν

επιλογή και την ηχητική διεπαφή. Ένα είναι σαφές. Οι κλάσεις που θα προ-

κύψουν για την υλοποίηση της συγκεκριµένης σε κάθε περίπτωση διεπαφής,

θα πρέπει να έχουν τη µικρότερη δυνατή σύζευξη (coupling) µε τις κλάσεις

που προκύπτουν από την περιοχή του προβλήµατος (problem space). Η δια-

δικασία της αναγνώρισης των κλάσεων των δύο χώρων, του προβλήµατος

και αυτής της λύσης (solution space), είναι µια σύνθετη διαδικασία που το

αποτέλεσµα της προσδιορίζει την ποιότητα σχεδιασµού της εφαρµογής. Η δια-

δικασία αυτή που περιγράφεται από τις αντικειµενοστρεφείς µεθοδολογίες

Ανάλυσης και Σχεδιασµού συστηµάτων λογισµικού, είναι εκτός των ορίων

του παρόντος βιβλίου.

Στο κεφάλαιο αυτό σας δίνεται ένα µεγάλο τµήµα του πηγαίου κώδικα µιας

ενδεικτικής υλοποίησης. Χρησιµοποιήστε το σταδιακά για υποβοήθησή σας,

καθώς θα αναπτύσσετε τη δική σας έκδοση. Στη διεύθυνση

http://seg.clab.ee.upatras.gr/calc.htm µπορείτε να βρείτε δύο υλοποιήσεις

της άσκησης. Μπορείτε να αναφερθείτε στις δύο υλοποιήσεις κατά τη διαδι-

κασία ανάπτυξης της δικής σας έκδοσης.

Ανατρέξτε στην θεµατική ενότητα 3.4 και εκτελέστε την «άσκηση για

παραπέρα εξάσκηση 1». Το θεωρώ απολύτως απαραίτητο για την παραπέ-

ρα µελέτη του κεφαλαίου.

¢Ú·ÛÙËÚÈfiÙËÙ·7.1

Page 129: Γλώσσες Προγραμματισμού II

7.1 ∞Ó·ÁÓÒÚÈÛË ∞ÓÙÈÎÂÈ̤ӈÓ

Η αναγνώριση των αντικειµένων της εφαρµογής αποτελεί ένα από τα σηµα-

ντικότερα βήµατα στη φάση της ανάπτυξης της και περιγράφεται από τις

διάφορες αντικειµενοστρεφείς µεθοδολογίες ανάπτυξης συστηµάτων λογι-

σµικού. Μια πολύ καλή αναφορά στο θέµα που είναι έξω από τα πλαίσια

του παρόντος βιβλίου, µπορείτε να βρείτε στην ενότητα 4.2 «Identifying

Classes and Objects» του κεφαλαίου 4 «Classification» του [Booch 94,]

όπου γίνεται µια επισκόπηση των πιο γνωστών τεχνικών, δίνοντας τις

κατάλληλες αναφορές.

1 2 9∞ ¡ ∞ ° ¡ ø ƒ π ™ ∏ ∞ ¡ ∆ π ∫ ∂ π ª ∂ ¡ ø ¡

Μελετήστε την ενότητα 1.2 του πρώτου κεφαλαίου του βιβλίου. Σύµφωνα

µε τη θεώρηση της ενότητας αυτής θα πρέπει να δούµε την αριθµοµηχανή

µας αποτελούµενη από ένα σύνολο από αντικείµενα, τα οποία συνεργαζό-

µενα µεταξύ τους θα προσφέρουν τις υπηρεσίες που θέλουµε. Αναγνωρί-

στε τα βασικά αντικείµενα από τα οποία αποτελείται µια αριθµοµηχανή.

Σηµειώσε ότι στη φάση αυτή πρέπει να καταγράψουµε αντικείµενα από το

χώρο του προβλήµατος και όχι από το χώρο επίλυσης.

¢Ú·ÛÙËÚÈfiÙËÙ·7.2

Αναγνωρίστε και καταγράψτε τις σχέσεις µεταξύ των αντικειµένων της

Αριθµοµηχανής.

Χρησιµοποιήστε την UML σηµειολογία για να δηµιουργήσετε το διά-

γραµµα κλάσεων.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘7.1

7.2 √ÚÈÛÌfi˜ ‚·ÛÈÎÒÓ ÏÂÈÙÔ˘ÚÁÈÒÓ

Στο βήµα αυτό θα ορίσουµε τις βασικές λειτουργίες που θα πρέπει να παρέ-

χει κάθε αντικείµενο, τις ευθύνες (responsibilities) δηλαδή κάθε κλάσης σαν

συνθετικό του όλου συστήµατος. Για µια πολύ καλή περιγραφή της διαδι-

κασίας αυτής µπορείτε να ανατρέξετε στη µεθοδολογία CRC (Class

Responsibility Collaborations) [Wilkinson 95]. Σε κάθε περίπτωση όµως, οι

µεθοδολογίες αυτές αποτελούν αντικείµενο του Software Engineering.

Θα ξεκινήσουµε από την κλάση Stack στην οποία αναφερθήκαµε στην αρχή

του κεφαλαίου 3. Το ευτυχές στη φάση αυτή είναι ότι η βασική βιβλιοθήκη

της Java περιλαµβάνει µια υλοποίηση της κλάσης Stack. H κλάση ανήκει

Page 130: Γλώσσες Προγραμματισμού II

1 3 0 ∫ ∂ º ∞ § ∞ π √ 7 : A ¡ ∞ ¶ ∆ À • ∏ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ E º ∞ ƒ ª √ ° ∏ ™

στο πακέτο util το οποίο θα πρέπει να κάνετε import στην αρχή του προ-

γράµµατός σας χρησιµοποιώντας την πρόταση

import java.util.*;

Η λίστα των µεθόδων της κλάσης Stack, όπως δίνεται από το JavaTM

Platform 1.2 API Specification[1], έχει ως ακολούθως:

SSttaacckk( ) // Creates an empty Stack

boolean eemmppttyy() // Tests if this stack is empty.

Object ppeeeekk()

//Looks at the object at the top of this stack

//without removing it from the stack.

Object ppoopp()

// Removes the object at the top of this stack and

//returns that object as the value of

// this function.

Object ppuusshh(Object item) // Pushes an item onto the

// top of this stack.

int sseeaarrcchh(Object o) // Returns the 1–based position

// where an object is on this

// stack.

Θα πρέπει να παρατηρήσουµε ότι ο τύπος του αντικειµένου που δέχεται η

στοίβα είναι Object. Το γεγονός αυτό δεν δηµιουργεί πρόβληµα, γιατί όπως

σίγουρα θα θυµόσασtε στη Java, όλες οι κλάσεις είναι απόγονοι της κλάσης

Object που αποτελεί τη ρίζα του δένδρου κληρονοµικότητας. Καθώς δε κάθε

στιγµιότυπο κλάσης απογόνου µπορεί να θεωρηθεί στιγµιότυπο προγόνου

κλάσης, µπορούµε να αποθηκεύσουµε στη στοίβα οποιοδήποτε αντικείµε-

νο. Προσέξτε όµως, όχι µεταβλητές πρωτογενών τύπων της Java.

√È ÚˆÙÔÁÂÓ›˜ Ù‡ÔÈ ‰Â‰ÔÌ¤ÓˆÓ Û·Ó ÎÏ¿ÛÂȘ:

Η Java µας δίνει τη δυνατότητα να χειριστούµε τους πρωτογενείς τύπους σαν

αντικείµενα. Για το σκοπό αυτό παρέχει µια κλάση για κάθε πρωτογενή τύπο.

Οι κλάσεις Character, Byte, Int, και Double, αντιστοιχούν στους

πρωτογενείς τύπους char, byte, int και double. Έτσι η πρόταση

double d = 12.0;

Page 131: Γλώσσες Προγραμματισμού II

Κλάση Adder

Για να εκτελέσει ένας τελεστής τη βασική διεργασία που αναπαριστά, θα

πρέπει να δεχθεί το µήνυµα operate. Η συµπεριφορά του τελεστή στο

µήνυµα αυτό ορίζεται από µια µέθοδο που έχει το ίδιο όνοµα µε το µήνυµα.

Επειδή η συµπεριφορά του κάθε επιµέρους τελεστή είναι διαφορετική, η

µέθοδος θα οριστεί στην κλάση Operator σαν abstract και καθεµιά από τις

υποκλάσεις της θα δίνει τη δική της υλοποίηση. Έτσι, ο χρήστης ενός τελε-

στή στέλνει το µήνυµα operate, χωρίς να απαιτείται να γνωρίζει τον ακριβή

τύπο του αντικειµένου–παραλήπτη (πολυµορφισµός).

1 3 1√ ƒ π ™ ª √ ™ µ ∞ ™ π ∫ ø ¡ § ∂ π ∆ √ À ƒ ° π ø ¡

δηλώνει µια µεταβλητή d, η οποία όµως είναι πρωτογενούς τύπου, δεν µπο-

ρεί να χρησιµοποιηθεί σαν αντικείµενο και κατά συνέπεια δεν µπορεί να

τοποθετηθεί στη στοίβα. Αντίθετα η πρόταση:

Double d = new Double(12.0);

δηλώνει µια αναφορά d, την οποία ο τελεστής ανάθεσης βάζει να δείχνει

στο στιγµιότυπο τύπου Double, που το δεύτερο µέλος της πρότασης ανά-

θεσης δηµιουργεί, και το οποίο έχει τιµή 12.0. Το στιγµιότυπο αυτό είναι

τύπου Object και µπορεί να τοποθετηθεί στη στοίβα.

Θεωρήστε τη µέθοδο operate της κλάσης Adder. ∆ώστε µια περιγραφή του

σώµατος της µε δοµηµένα Ελληνικά.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘7.2

∆ώστε σε Java το σώµα της µεθόδου operate της κλάσης Adder. Θεω-

ρείστε την περιγραφή που σας δόθηκε στην απάντηση της άσκησης αυτο-

αξιολόγησης 2 και ότι η τιµή του τελεστέου αποθηκεύεται σε µεταβλητή

τύπου Double.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘7.3

Κλάση Operand

Για την υλοποίηση της κλάσης Operand κάντε την παραδοχή ότι ο χρήστης,

θα δίνει ένα–ένα τα ψηφία του τελεστέου, θα µπορεί να διαγράψει το τελευταίο

στοιχείο που έδωσε και θα µπορεί να µηδενίσει το περιεχόµενο του τελεστέου.

Page 132: Γλώσσες Προγραμματισμού II

1 3 2 ∫ ∂ º ∞ § ∞ π √ 7 : A ¡ ∞ ¶ ∆ À • ∏ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ E º ∞ ƒ ª √ ° ∏ ™

7.3 ¢ËÌÈÔ˘ÚÁ›· ÚÒÙ˘ ¤Î‰ÔÛ˘ ÙÔ˘ ÚÔÁÚ¿ÌÌ·ÙÔ˜ Ù˘ ·ÚÈıÌÔ-Ì˯·Ó‹˜

Στη φάση αυτή έχουµε τα βασικά αντικείµενα µε τα οποία µπορούµε να δηµι-

ουργήσουµε την πρώτη έκδοση του προγράµµατος της αριθµοµηχανής. Η

πρώτη αυτή έκδοση θα έχει πολύ περιορισµένη λειτουργικότητα. Απλά θα

υπολογίζει το άθροισµα του 12.0 και του 4.0, αλλά θα χρησιµοποιεί για το

σκοπό αυτό τα αντικείµενα που ορίσαµε παραπάνω.

Η έκδοση αυτή θα µας βοηθήσει στον έλεγχο των βασικών αντικειµένων της

εφαρµογής αλλά και στην κατανόηση του τρόπου συνεργασίας (object

collaboration) τους. Τι θα κάνει το πρόγραµµα µας;

Θα δηµιουργεί έναν τελεστέο µε τιµή 12.0,

θα δηµιουργεί έναν τελεστέο µε τιµή 4.0,

θα ενεργοποιεί τον Adder,

θα ενεργοποιεί τον τελεστή ResultPresenter.

Μήπως τα παραπάνω είναι η περιγραφή της συµπεριφοράς της πρώτης αυτής

έκδοσης της αριθµοµηχανής µας; Ή διαφορετικά το σώµα της µεθόδου main

της κλάσης Calculator, που για λόγους συντοµίας ονοµάζουµε στη συνέ-

χεια Calc; Στη συνέχεια δίνεται ένας πρώτος ορισµός της κλάσης Calc:

public class Calc

public static Stack s;

public static Adder add;

public static ResultPresenter rp;

public static Operand op;

public static void main(String[] argv)

….

∆ώστε σε Java τον ορισµό της κλάσης Operand θεωρώντας ότι η κλάση

έχει σαν δεδοµένα µια µεταβλητή τύπου double. Στην πρώτη αυτή έκδο-

ση δεν είναι απαραίτητο να δώσετε το σώµα των µεθόδων.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

7.4

Page 133: Γλώσσες Προγραμματισμού II

7.4 √ÏÔÎÏ‹ÚˆÛË Ù˘ ÎÏ¿Û˘ Operand

Αποµένει τώρα ο ορισµός των µεθόδων addDigit και deleteLast

Digit. Για την υλοποίηση των µεθόδων αυτών είναι προτιµότερο να θεω-

ρήσουµε τη µεταβλητή της Operand σαν αλφαριθµητικό, το οποίο θα ανα-

παραστήσουµε µε µια µεταβλητή τύπου StringBuffer. Ορίζουµε ένα

δηµιουργό, ο οποίος δηµιουργεί ένα στιγµιότυπο της buf, δεσµεύοντας 14

bytes. Επειδή θέλουµε να έχουµε ταυτόχρονα δυνατότητα δηµιουργίας στιγ-

µιότυπου µε άµεση απόδοση τιµής, ορίζουµε το δηµιουργό Operand

(double). H Operand διαµορφώνεται όπως παρακάτω:

class Operand

private StringBuffer buf;

public Operand()

buf = new StringBuffer(14);

public Operand(double val)

this();

buf.append(Double.toString(val));

1 3 3√ § √ ∫ § ∏ ƒ ø ™ ∏ ∆ ∏ ™ ∫ § ∞ ™ ∏ ™ O P E R A N D

∆ώστε το σώµα της µεθόδου main της κλάσης Calc που ορίσαµε στην

ενότητα 7.3.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘7.5

Έχετε τώρα στη διάθεση σας όλα τα αντικείµενα από τα οποία απαρτίζε-

ται η πρώτη έκδοση της αριθµοµηχανής σας. Προχωρήστε στην σύνθεση

του πηγαίου κώδικα. Εκτελέστε και ελέγξτε τη συµπεριφορά του.

¢Ú·ÛÙËÚÈfiÙËÙ·7.3

Προχωρήστε στον ορισµό της operate για τους υπόλοιπους τελεστές. Προ-

σέξτε ιδιαίτερα τους τελεστές αφαίρεσης και διαίρεσης. Υλοποιήστε µια

δεύτερη έκδοση η οποία θα επιδεικνύει τη χρήση όλων αυτών των τελεστών.

Αφιερώστε πολύ χρόνο, προσπαθώντας να δώσετε µόνοι σας τη λύση.

¢Ú·ÛÙËÚÈfiÙËÙ·7.4

Page 134: Γλώσσες Προγραμματισμού II

1 3 4 ∫ ∂ º ∞ § ∞ π √ 7 : A ¡ ∞ ¶ ∆ À • ∏ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ E º ∞ ƒ ª √ ° ∏ ™

public void addDigit(char ch)buf.append(ch);;

public void deleteLastDigit();

public void reset() ;

public void set(double val) value = val;

public void complete()

Double d = new Double(buf.toString());

Calc.s.push(d);

reset();

Προσέξτε τη µέθοδο complete. Θα µπορούσε να γραφεί και ως εξής:

public void complete()

Calc.s.push(new Double(buf.toString()));

reset();

Αναπτύξτε ένα πρόγραµµα για τον έλεγχο της κλάσης Operand. Αφιερώ-

στε αρκετό χρόνο µπροστά στον υπολογιστή σας πριν καταφύγετε στην

ενδεικτική λύση που σας δίνουµε στο τέλος του βιβλίου.

¢Ú·ÛÙËÚÈfiÙËÙ·7.5

Προχωρήστε στον ορισµό των υπόλοιπων µεθόδων της κλάσης Operand.

Είναι προφανές ότι η υλοποίηση αυτή προϋποθέτει καλή γνώση των κλά-

σεων String και StringBuffer της βασικής βιβλιοθήκης της Java. Σ’

ένα επόµενο βήµα εµπλουτίστε το πρόγραµµα που είχατε αναπτύξει για τον

έλεγχο της Operand στη δραστηριότητα 5 ώστε να επιδεικνύει και τη

χρήση των υπόλοιπων µεθόδων της.

¢Ú·ÛÙËÚÈfiÙËÙ·7.6

Page 135: Γλώσσες Προγραμματισμού II

7.5 ∞Ó¿Ù˘ÍË ÁÚ·ÊÈ΋˜ ‰È·ʋ˜ (GUI) Ì ÙÔÓ ¯Ú‹ÛÙË

Έχουµε όλα τα αντικείµενα που είναι απαραίτητα για τη λειτουργία της αριθ-

µοµηχανής. Αυτό που µας λείπει είναι ο προσδιορισµός του τρόπου µε τον

οποίο ο χρήστης θα επικοινωνεί µε τα αντικείµενα αυτά. Πρέπει να ορίσου-

µε ένα σύνολο από γραφικά αντικείµενα, τα οποία θα υποστηρίζουν την επι-

κοινωνία του χρήστη µε τα αντικείµενα που ήδη αναπτύξαµε και τα οποία

µπορούµε να πούµε ότι συνθέτουν τη µηχανή (engine) της αριθµοµηχανής

µας. Ας θεωρήσουµε σαν βάση, τη γραφική διεπαφή (GUI) του calculator

των Accessories των MS Windows που δίνεται στο σχήµα 7.1. Μια λίστα µε

ορισµένα από τα αντικείµενα της διεπαφής δίνεται στη συνέχεια:

• Display

• DigitButton

• ControlButton

• OperatorButton

• MemoryButton

1 3 5∞ ¡ ∞ ¶ ∆ À • ∏ ° ƒ∞ º π ∫ ∏ ™ ¢ π ∂ ¶ ∞ º ∏ ™ ( G U I ) ª ∂ ∆ √ ¡ à ƒ ∏ ™ ∆ ∏

Αναπτύξτε τη δική σας διεπαφή για την αριθµοµηχανή. Κάτι τέτοιο προϋπο-

θέτει εξοικείωση µε το πακέτο awt ή τη χρήση ενός ολοκληρωµένου περι-

βάλλοντος ανάπτυξης (SDE), όπως Visual Café, Microsoft J++, κ.λπ. Θα

χρειαστεί να ανατρέξετε στην τεκµηρίωση της βασικής βιβλιοθήκης της Java

και πιθανώς σε κάποιο από τα πολλά βιβλία που κυκλοφορούν και αναφέ-

ρονται στην ανάπτυξη GUI µε Java. Μια πιο απλή διεπαφή µπορείτε να βρεί-

τε στις δύο ενδεικτικές υλοποιήσεις που µπορείτε να βρείτε στο διαδίκτυο.

ÕÛÎËÛË ÁÈ· ·Ú·¤Ú· ÂÍ¿ÛÎËÛË 7.1

™¯‹Ì· 7.1

Γραφική διεπαφή (GUI)

του calculator των

Accessories των MS

Windows

Page 136: Γλώσσες Προγραμματισμού II

1 3 6 ∫ ∂ º ∞ § ∞ π √ 7 : A ¡ ∞ ¶ ∆ À • ∏ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ E º ∞ ƒ ª √ ° ∏ ™

7.6 ∞ÓÙ·ÏÏ·Á‹ ÌËÓ˘Ì¿ÙˆÓ ÌÂٷ͇ Ì˯·Ó‹˜ Î·È ·ÓÙÈÎÂÈÌ¤ÓˆÓ ‰È·ʋ˜

Στο βήµα αυτό θα ασχοληθούµε µε τον προσδιορισµό της ανταλλαγής µηνυ-

µάτων µεταξύ των αντικειµένων της διεπαφής και αυτών της µηχανής

(engine).

Κλάση DigitButton

Η κλάση έχει σαν δεδοµένο (instance variable) το ψηφίο που εµφανίζει. Η

συµπεριφορά των αντικειµένων της είναι απλή. Όταν ένα στιγµιότυπο της

κλάσης δεχθεί το πάτηµα του mouse θα αποστείλει ένα µήνυµα addDigit

στο στιγµιότυπο Operand της µηχανής. Η παράµετρος του µηνύµατος θα

είναι το ψηφίο που αναπαριστά το συγκεκριµένο στιγµιότυπο. Αυτό βέβαια

προϋποθέτει ότι το στιγµιότυπο τύπου operand είναι ορατό στο στιγµιότυπο

DigitButton. Ανατρέξτε στο κεφάλαιο 5 για να επιλέξετε τον τρόπο µε τον

οποίο προσφέρεται µια τέτοια πρόσβαση.

ªÂÙ·ıÂÌ·ÙÈ΋ ÛËÌÂÈÔÏÔÁ›·.

Η µεταθεµατική σηµειολογία θέλει διαφορετική αντιµετώπιση από την

ενθεµατική µε την οποία είµαστε εξοικειωµένοι. Η διαφορά εντοπίζεται

στην εισαγωγή των τελεστέων. Επειδή οι τελεστέοι εισάγονται ο ένας µετά

τον άλλον πιθανώς χωρίς τη διαµεσολάβηση τελεστή, θα πρέπει να προσ-

διορίσουµε µε ποιο τρόπο ο χρήστης θα ορίζει την ολοκλήρωση του κάθε

τελεστέου που εισάγει. ∆εχόµαστε ότι ο χρήστης θα πρέπει να πατά το πλή-

κτρο Enter για να δηλώσει στην αριθµοµηχανή την ολοκλήρωση του τελε-

στέου. Το Enter, όταν δέχεται κλικ, θα αποστέλλει ένα µήνυµα complete

στο στιγµιότυπο τύπου Operand της κλάσης Calc.

Κλάση OperatorButton

Αν ορίσουµε κλάσεις AddButton, SubButton, κ.λπ. τα στιγµιότυπα των

κλάσεων αυτών όταν δέχονται το κλικ του mouse θα αποστέλλουν το µήνυ-

µα operate στο αντίστοιχο στιγµιότυπο τύπου Adder, Subtracter, κ.λπ.

της µηχανής. Αν υπάρχει µόνο τύπος OperatorButton, τότε το στιγµιότυ-

πο της θα αποφασίζει ανάλογα µε τη διεργασία που αναπαριστά σε ποιό στιγ-

µιότυπο θα αποστείλει το µήνυµα operate.

Page 137: Γλώσσες Προγραμματισμού II

1 3 7∞ ¡ ∆∞ § § ∞ ° ∏ ª ∏ ¡ À ª ∞∆ ø ¡ ª ∂ ∆∞ • À ª ∏ Ã ∞ ¡ ∏ ™ ∫ ∞ π ∞ ¡ ∆ π ∫ ∂ π ª ∂ ¡ ø ¡ ¢ π ∂ ¶ ∞ º ∏ ™

Θεωρήστε και τις δύο παραπάνω υλοποιήσεις. Σχολιάστε. ÕÛÎËÛË ÁÈ· ·Ú·¤Ú· ÂÍ¿ÛÎËÛË 7.2

Προσδιορίστε τη συµπεριφορά των στιγµιότυπων

MCButton MRButton

MplusButton MSButton

τα οποία αναπαριστούν τις διεργασίες που έχουν σχέση µε τη µνήµη της

αριθµοµηχανής

ÕÛÎËÛË ÁÈ· ·Ú·¤Ú· ÂÍ¿ÛÎËÛË 7.3

Προχωρήστε στην ολοκλήρωση (integration) των διαφόρων κλάσεων που

αναπτύξατε, ώστε να συνθέσετε την αριθµοµηχανή σας. Θα είστε σίγουρα

περήφανοι γι’ αυτήν.

ÕÛÎËÛË ÁÈ· ·Ú·¤Ú· ÂÍ¿ÛÎËÛË 7.4

Κλάση CButton

Onclik αποστέλλει µήνυµα clear στο σωρό της Calc.

CEButton

Onclik αποστέλλει µήνυµα reset στο στιγµιότυπο τύπου Operand της Calc.

BackButton

Onclik αποστέλλει µήνυµα deleteLastDigit στο στιγµιότυπο τύπου

Operand της Calc.

™ÂÓ¿ÚÈÔ ÏÂÈÙÔ˘ÚÁ›·˜ ∞ÚÈıÌÔÌ˯·Ó‹˜

Ακολουθεί η περιγραφή ενός σεναρίου λειτουργίας της αριθµοµηχανής για

τον υπολογισµό της τιµής της έκφρασης

13 6 + 8 6 – *

O χρήστης πιέζει το πλήκτρο 1. Αυτό αποστέλλει το µήνυµα addDigit(‘1’)

στο στιγµιότυπο Operand της Calc.

(συνέχεια…)

Page 138: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 7 : A ¡ ∞ ¶ ∆ À • ∏ A ¡ ∆ π ∫ ∂ π ª ∂ ¡ √ ™ ∆ ƒ ∂ º √ À ™ E º ∞ ƒ ª √ ° ∏ ™1 3 8

(…συνέχεια)

O χρήστης πιέζει το πλήκτρο 3. Αυτό αποστέλλει το µήνυµα addDigit(‘3’)

στο στιγµιότυπο Operand της Calc.

O χρήστης πιέζει το πλήκτρο Enter. Αυτό αποστέλλει το µήνυµα complete

στο στιγµιότυπο Operand της Calc, το οποίο µε τη σειρά του αποστέλλει το

µήνυµα push στην στοίβα, η οποία αποθηκεύει ένα αντικείµενο µε τιµή 13.

O χρήστης πιέζει το πλήκτρο 6. Αυτό αποστέλλει το µήνυµα addDigit(‘6’)

στο στιγµιότυπο Operand της Calc.

O χρήστης πιέζει το πλήκτρο Enter. Αυτό αποστέλλει το µήνυµα complete

στο στιγµιότυπο Operand της Calc, το οποίο µε τη σειρά του αποστέλλει το

µήνυµα push στη στοίβα, η οποία αποθηκεύει ένα αντικείµενο µε τιµή 6.

O χρήστης πιέζει το πλήκτρο +. Αυτό αποστέλλει το µήνυµα operate στο

στιγµιότυπο Adder της Calc. O Adder αποστέλλει ένα µήνυµα pop στη

στοίβα για να πάρει τον ένα τελεστέο. Στη συνέχεια αποστέλλει ένα ακόµη

µήνυµα pop στη στοίβα για να πάρει το δεύτερο τελεστέο. Τους προσθέτει

και αποστέλλει ένα µήνυµα push στη στοίβα για να βάλει µέσα το 19.

O χρήστης πιέζει το πλήκτρο 8. …

O χρήστης πιέζει το πλήκτρο Enter. …

O χρήστης πιέζει το πλήκτρο 6. …

O χρήστης πιέζει το πλήκτρο Enter. …

O χρήστης πιέζει το πλήκτρο –. …

O χρήστης πιέζει το πλήκτρο *. Αυτό αποστέλλει το µήνυµα operate στο

στιγµιότυπο Multiplier της Calc. O Multiplier αποστέλλει ένα µήνυµα pop

στη στοίβα για να πάρει τον ένα τελεστέο (2). Στη συνέχεια αποστέλλει ένα

ακόµη µήνυµα pop στη στοίβα για να πάρει τον δεύτερο τελεστέο (19).

Τους πολλαπλασιάζει και αποστέλλει ένα µήνυµα push στη στοίβα για να

βάλει µέσα το 38.

O χρήστης πιέζει το πλήκτρο Enter. Αυτό αποστέλλει το µήνυµα operate

στο στιγµιότυπο ResultPresenter της Calc. O ResultPresenter αποστέλλει

ένα µήνυµα pop στην στοίβα για να πάρει ένα τελεστέο (38). Στη συνέ-

χεια αποστέλλει ένα µήνυµα στο στιγµιότυπο Display για να εµφανίσει το

αποτέλεσµα.

Page 139: Γλώσσες Προγραμματισμού II

™‡ÓÔ„Ë

Παρακολουθήσαµε βήµα προς βήµα τη διαδικασία για την ανάπτυξη µιας

πραγµατικής εφαρµογής µε την αντικειµενοστρεφή προσέγγιση. Υιοθετήσαµε

τη διαδικασία της αυξητικής (incremental) ανάπτυξης, κατά την οποία ανα-

πτύσσουµε την εφαρµογή σε διαδοχικά βήµατα όπου στο κάθε βήµα ανα-

πτύσσουµε, ελέγχουµε και ολοκληρώνουµε στον υπόλοιπο κώδικα περιορι-

σµένο αριθµό κλάσεων.

Αρχίσαµε από την αναγνώριση των βασικών αντικειµένων της εφαρµογής.

Οι αντικειµενοστρεφείς µεθοδολογίες ανάλυσης έχουν να προσφέρουν πολλά

στο θέµα αυτό, που είναι από τα πιο βασικά στην ανάπτυξη µιας εφαρµογής.

Προχωρήσαµε στον ορισµό των βασικών λειτουργιών έχοντας σαν στόχο την

παροχή της αναµενόµενης από κάθε κλάση συµπεριφοράς στα πλαίσια της

συνεργασίας της κάθε κλάσης µε τις υπόλοιπες της εφαρµογής.

BÈ‚ÏÈÔÁÚ·Ê›·

[1] [Wilkinson 95]

Nancy Wilkinson «Using CRC cards: An informal Approach to

Object–Oriented Development» SIGS Books, AT&T Bell

Laboratories,1995.

1 3 9™ Y N O æ H / B I B § I O ° PA º I A

Page 140: Γλώσσες Προγραμματισμού II
Page 141: Γλώσσες Προγραμματισμού II

XÂÈÚÈÛÌfi˜ EÍ·ÈÚ¤ÛˆÓ

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να εισάγει την τεχνική της διαχείρισης εξαι-

ρέσεων σαν θεµέλιο λίθο για τη συγγραφή εύρωστων και αξιόπιστων προ-

γραµµάτων, καθώς και τις κατασκευές της Java που υποστηρίζουν την

τεχνική αυτή.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• περιγράψετε την τεχνική του χειρισµού εξαιρέσεων,

• αναφέρετε δύο τουλάχιστο λόγους που καθιστούν το χειρισµό εξαιρέσεων

επιτακτικό,

• περιγράψετε πώς η C χειρίζεται τις εξαιρέσεις,

• δώσετε πέντε τουλάχιστο παραδείγµατα εξαιρέσεων,

• αναφέρετε τους βασικούς στόχους του µηχανισµού χειρισµού εξαιρέσεων

της Java,

• χρησιµοποιείτε µεθόδους της βασικής βιβλιοθήκης που εγείρουν εξαιρέσεις,

• συλλαµβάνετε και αντιµετωπίζετε εξαιρέσεις,

• ορίζετε µεθόδους που εγείρουν εξαιρέσεις,

• περιγράψετε τη συµπεριφορά του Java περιβάλλοντος σε περίπτωση που

µια εξαίρεση δε συλληφθεί από το πρόγραµµα που τη δηµιούργησε,

• δηλώνετε τους κατάλληλους για κάθε περίπτωση τύπους εξαίρεσης,

• χρησιµοποιείτε σωστά τις προτάσεις try/catch/finally και throws.

8∫ ∂ º ∞ § ∞ π √

• εξαίρεση (exception)

• χειρισµός εξαιρέσεων

(exception handling)

• resumption model of exception

handling

• termination model of exception

handling

• έγερση εξαίρεσης

• σύλληψη εξαίρεσης

ŒÓÓÔȘ ÎÏÂȉȿ

Page 142: Γλώσσες Προγραμματισμού II

1 4 2 ∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Στόχος δικός σας, αλλά και κάθε προγραµµατιστή, είναι η συγγραφή κώδικα

που θα έχει σαν αποτέλεσµα προγράµµατα που δε θα καταρρέουν ποτέ. Αυτό

σηµαίνει πως ο κώδικας σας πρέπει να είναι διαµορφωµένος έτσι ώστε να

ανιχνεύει και να αντιµετωπίζει κατάλληλα κάθε δυνατή κατάσταση που µπο-

ρεί να οδηγήσει σε σφάλµα. Για να γίνουµε πιο κατανοητοί, θα θεωρήσουµε

σαν παράδειγµα τη συνάρτηση ή µέθοδο pop της στοίβας από την ενότητα 3.1

του κεφαλαίου 3. Η pop καλείται για να επιστρέψει από τη στοίβα το τελευ-

ταίο εισαχθέν αντικείµενο. Τι θα συµβεί όµως, αν η στοίβα δεν έχει αντικεί-

µενο, δηλαδή, είναι άδεια; Προφανώς η pop θα πρέπει να ελέγξει, αν υπάρ-

χει διαθέσιµο αντικείµενο. Και αν µεν υπάρχει αντικείµενο, η pop λειτουργεί

κανονικά, το παίρνει και το επιστρέφει στη µέθοδο που την κάλεσε. Αν όµως

δεν υπάρχει αντικείµενο, ποια θα είναι η συµπεριφορά της; Θα πρέπει να

αναγνωρίσει η ίδια την κατάσταση αυτή και να τη χειριστεί κατάλληλα; Ή

µήπως θα πρέπει να ενηµερώσει τη µέθοδο που την κάλεσε θεωρώντας πως

αυτή είναι ικανή να χειριστεί κατάλληλα τη συγκεκριµένη κατάσταση; Προ-

φανώς εξαρτάται από την περίπτωση και είναι ευθύνη του προγραµµατιστή

να επιλέξει. Για την υλοποίηση όµως της κάθε επιλογής του η γλώσσα δια-

θέτει τις κατάλληλες εκείνες κατασκευές που θα διασφαλίσουν αξιόπιστο

κώδικα; Η C, για παράδειγµα, δε διαθέτει ειδική κατασκευή για το χειρισµό

των εξαιρέσεων. Αντίθετα, οι σχεδιαστές πολλών σύγχρονων γλωσσών προ-

γραµµατισµού αναγνωρίζοντας το σηµαντικό αυτό πρόβληµα εφοδίασαν τις

γλώσσες αυτές µε κατασκευές που επιτρέπουν στον προγραµµατιστή να χει-

ριστεί τα σφάλµατα (εξαιρετικές περιπτώσεις) µε αποδοτικό τρόπο. Ο νέος

αυτός τρόπος χειρισµού είναι γνωστός µε το όνοµα χειρισµός εξαιρέσεων

(exception handling) και αποτελεί αντικείµενο του παρόντος κεφαλαίου.

Το κεφάλαιο είναι οργανωµένο σε δύο ενότητες. Στην πρώτη παρουσιάζεται

η τεχνική της διαχείρισης εξαιρέσεων γενικά και ανεξάρτητα από συγκεκρι-

µένη υλοποίηση, ενώ στη δεύτερη παρουσιάζονται οι κατασκευές της Java

που υποστηρίζουν το χειρισµό των εξαιρέσεων. Καθώς οι κατασκευές αυτές

είναι ιδιαίτερα σύνθετες, θα χρειασθεί ιδιαίτερη προσοχή στη µελέτη του

• πρόταση try/catch/finally

• throws τµήµα

• πρόταση throw

• κλάση Throwable

• κλάση Exception

Page 143: Γλώσσες Προγραμματισμού II

κεφαλαίου. Αφιερώστε τον ανάλογο χρόνο, καθώς πρόκειται για ένα µηχα-

νισµό του οποίου η προσεκτική χρήση θα βελτιώσει σε µεγάλο βαθµό την

αξιοπιστία και ευρωστία των προγραµµάτων σας. Για µια πολύ αναλυτική

αναφορά στο µηχανισµό χειρισµού εξαιρέσεων της Java µπορείτε να ανα-

τρέξετε στο κεφάλαιο 12 του [Deitel 98].

1 4 3∂ π ™ ∞ ° ø ° π ∫ ∂ ™ ¶ ∞ ƒ∞∆ ∏ ƒ ∏ ™ ∂ π ™

∂Í·ÈÚ¤ÛÂȘ ÛÙÔ «fast–food o °ÈÒÚÁÔ˜»

Το σύστηµα του fast–food, του αντίστοιχου παραδείγµατος του κεφαλαίου

1, αποτελείται από ένα σύνολο από αντικείµενα τα οποία συνεργάζονται

µεταξύ τους για την παροχή υπηρεσιών προς τον έξω κόσµο. Η Μαίρη,

όταν προσλήφθηκε, πήρε οδηγίες για το πώς θα ενεργεί σε απόκριση ορι-

σµένων µηνυµάτων που θα δέχεται ή συµβάντων που θα αναγνωρίζει.

Θα θεωρήσουµε ένα από τα µηνύµατα αυτά και συγκεκριµένα το «ένα τοστ

µε ζαµπόν–τυρί παρακαλώ» για το οποίο εκ πρώτης όψης η συµπεριφορά

της Μαίρης είναι πλήρως ορισµένη. Ας θεωρήσουµε όµως την παρακάτω

εξαιρετική περίπτωση που είναι πιθανή καθώς η Μαίρη προετοιµάζει το

τοστ. Στην εκτέλεση της ενέργειας «πάρε τυρί», διαπιστώνει, ότι το τυρί

έχει τελειώσει. Το συµβάν αυτό χαρακτηρίζεται σαν εξαιρετική περίπτω-

ση και, αν η Μαίρη δεν έχει ενηµερωθεί πώς να την αναγνωρίσει και να

την χειριστεί, το σύστηµα κινδυνεύει να µεταπέσει σε κατάσταση απροσ-

διόριστης συµπεριφοράς. Υποθέτουµε πως η Μαίρη αναγνωρίζει το συµ-

βάν αυτό σαν εξαιρετική περίπτωση. Ποιά µπορεί να είναι η συµπεριφορά

της στην περίπτωση αυτή; Έχουµε τις παρακάτω επιλογές:

α) Η Μαίρη έχει την γνώση να χειριστεί τη συγκεκριµένη εξαίρεση, πρέ-

πει να εκτελέσει ένα σύνολο από ενέργειες, όπως «πάρε από το ψυγείο της

αποθήκης ένα κεφάλι τυρί», «κόψε το σε φέτες, », κ.λπ. Λέµε πως η Μαίρη

αναγνωρίζει την εξαίρεση, τη συλλαµβάνει και την αντιµετωπίζει. ∆εν είναι

απαραίτητο να ενηµερώσει το Γιώργο για την εξαιρετική αυτή περίπτωση.

β) Ο Γιώργος δε θέλει να αναθέσει στη Μαίρη την αντιµετώπιση της εξαι-

ρετικής αυτής περίπτωσης για διάφορους λόγους. Στην περίπτωση αυτή η

Μαίρη αναγνωρίζει την εξαιρετική περίπτωση, δηµιουργεί ένα µήνυµα,

όπως «δεν υπάρχει τυρί» (ένα αντικείµενο εξαίρεσης θα έλεγα), και το στέλ-

νει στο Γιώργο που της ανέθεσε το έργο της παρασκευής του τοστ. Λέµε

πως η Μαίρη στην περίπτωση αυτή ανιχνεύει την εξαιρετική περίπτωση,

(συνέχεια…)

Page 144: Γλώσσες Προγραμματισμού II

1 4 4 ∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡

8.1 H ¤ÓÓÔÈ· ÙÔ˘ ¯ÂÈÚÈÛÌÔ‡ ÂÍ·ÈÚ¤ÛˆÓ

Μια εξαίρεση είναι µια παρέκκλιση από την κανονική εξέλιξη µιας διαδικα-

σίας. Η παρέκκλιση αυτή, που µπορεί να οφείλεται σε εµφάνιση ενός λάθους

ή µιας εξαιρετικής περίπτωσης, επιβάλλει είτε τον άµεσο τερµατισµό του

προγράµµατος είτε την εκτέλεση συγκεκριµένων ενεργειών για τη διαχείρι-

ση της. Ο όρος εξαίρεση προσδιορίζει κάτι πιο γενικό από ένα σφάλµα, προσ-

διορίζει ένα συµβάν του οποίου η εµφάνιση στο χρόνο εκτέλεσης απαιτεί

ειδικό χειρισµό. Τέτοια συµβάντα µπορεί να είναι η αδυναµία να ανοιχθεί

ένα αρχείο, η αδυναµία ανάγνωσης του συγκεκριµένου αριθµού bytes, η αδυ-

ναµία στην εγγραφή, η µη ύπαρξη αντικειµένου σε µια στοίβα, κ.λπ.

Ο όρος χειρισµός εξαιρέσεων (exception handling) προσδιορίζει την ανα-

γνώριση της εξαίρεσης και τη µεταφορά του ελέγχου µε ταυτόχρονη µετα-

φορά της αναγκαίας πληροφορίας στην αλυσίδα των καλουσών (call chain)

διαδικασιών ώστε να καταστεί δυνατή η διαχείριση της από µια ανώτερη

ιεραρχικά διαδικασία. Σύµφωνα µε τον χειρισµό εξαιρέσεων η pop θα πρέ-

πει να αναγνωρίσει τη µη ύπαρξη αντικειµένου στη στοίβα και να το γνω-

στοποιήσει στη διαδικασία που την κάλεσε ώστε αυτή να χειριστεί την εξαι-

ρετική αυτή περίπτωση κατάλληλα.

Οι διάφορες γλώσσες προγραµµατισµού διαφέρουν στον τρόπο χειρισµού

των εξαιρέσεων. Για παράδειγµα στη C, η οποία δε διαθέτει ειδικό µηχανι-

σµό χειρισµού εξαιρέσεων, οι συναρτήσεις γνωστοποιούν στην καλούσα

συνάρτηση την εµφάνιση προβλήµατος στην κανονική λειτουργία τους, είτε

επιστρέφοντας ειδικές τιµές, είτε δίνοντας κατάλληλες τιµές σε καθολικές

(global) µεταβλητές. Η αντιµετώπιση αυτή έχει σαν αποτέλεσµα να οδη-

γούµαστε σε κώδικα όπου η λογική της κανονικής λειτουργίας «χάνεται»

(…συνέχεια)

εγείρει ένα αντικείµενο εξαίρεσης (throws an exception) και το µεταδίδει

(throws) στη διεργασία που την κάλεσε. Ο Γιώργος τώρα θα πρέπει να συλ-

λάβει (catch) την εξαίρεση και να την αντιµετωπίσει κατάλληλα.

Θέµατα όπως «σε ποιόν θα αναφέρει η Μαίρη την εξαίρεση;» «σε αυτόν

που της ζήτησε την εξυπηρέτηση ή πάντα στον Γιώργο;» «συνεχίζει την

δουλειά της µετά την έγερση της εξαίρεσης ή περιµένει να ολοκληρωθεί η

αντιµετώπιση της πρώτα;» κ.λπ. καθορίζουν την πολιτική διαχείρισης των

εξαιρετικών περιπτώσεων στη λειτουργία ενός συστήµατος.

Page 145: Γλώσσες Προγραμματισμού II

µέσα στον κώδικα που είναι απαραίτητος για την ανίχνευση και διαχείριση

των εξαιρέσεων. Και ναι µεν η διαχείριση των σφαλµάτων βελτιώνει την

αξιοπιστία του προγράµµατος, δηµιουργεί όµως πολλά προβλήµατα στη

διαύγεια του κώδικα. Υπάρχει ένας εµφανής ανταγωνισµός µεταξύ αξιοπι-

στίας (έλεγχος για κάθε δυνατό σφάλµα) και διαύγειας κώδικα (αποφυγή

ελέγχου κάθε σφάλµατος) [Gosling 96].

Το σχήµα 8.1 δίνει σε ψευδοκώδικα τη διαδικασία readFile χωρίς να λαµ-

βάνει υπόψη τη διαχείριση των εξαιρετικών περιπτώσεων, ενώ το σχήµα 8.2

έχει προσθέσει διαχείριση εξαιρετικών περιπτώσεων, όπως το αρχείο δεν

ανοίγει, το µέγεθος του δεν µπορεί να προσδιοριστεί, δεν υπάρχει αρκετή

µνήµη για ανάθεση, η ανάγνωση απέτυχε, κ.λπ. Είναι εµφανές ότι η παρα-

κολούθηση της ροής που παρουσιάζει την κανονική λειτουργία της διαδικα-

σίας είναι πολύ δύσκολη. Οι επτά γραµµές του ψευδοκώδικα χωρίς τη δια-

χείριση λαθών έχουν χαθεί µέσα στις 29 γραµµές του κώδικα που περιλαµ-

βάνει διαχείριση λαθών.

read_file

openTheFile;

determine its size;

allocate that much memory;

read the file into memory;

closeTheFile;

Η PL/1 ήταν η πρώτη γλώσσα που προσέφερε µηχανισµό για το χειρισµό

των εξαιρέσεων, επιτρέποντας στον προγραµµατιστή να γράφει πιο καθαρό,

εύρωστο και ανεκτικό σε λάθη (fault–tolerant) κώδικα. Μια διαδικασία καλεί

µία άλλη διαδικασία προκαλώντας µια ενεργοποίηση της. Η ενεργοποίηση

εκτελεί τη διεργασία την οποία αναπαριστά και τερµατίζει κανονικά, επι-

στρέφοντας τον έλεγχο στην διαδικασία που καλεί. Σε περίπτωση όµως που

προκύψει ένα συµβάν που η εµφάνιση του απαιτεί ειδικό χειρισµό, η ενερ-

γοποίηση θα προκαλέσει την έγερση µιας εξαίρεσης (throw an exception).

∆υο βασικά ερωτήµατα που προκύπτουν στην περίπτωση αυτή είναι: «Ποια

διαδικασία θα ενεργοποιηθεί για να χειριστεί την εξαίρεση;» και «Θα εξα-

κολουθήσει η διαδικασία που δηµιούργησε την εξαίρεση να είναι ενεργή;».

1 4 5H ∂ ¡ ¡ √ π ∞ ∆ √ À Ã ∂ π ƒ π ™ ª √ À ∂ • ∞ π ƒ ∂ ™ ∂ ø ¡

™¯‹Ì· 8.1

Ψευδοκώδικας χωρίς

διαχείριση λαθών.

Page 146: Γλώσσες Προγραμματισμού II

1 4 6 ∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡

ErrorCodeType read_file

ErrorCode = 0;

OOppeennTThheeFFiillee;;

If (theFileIsOpen)

ddeetteerrmmiinnee__ffiillee__lleennggtthh(());;

if (gotTheFileLength)

aallllooccaattee__tthhaatt__mmeemmoorryy(());;

if (gotEnoughMemory)

rreeaadd__ffiillee__ttoo__mmeemmoorryy(());;

if (readFailed) errorCode = –1;

else errorCode = –2;

else errorCode = –3;

cclloosseeTThheeFFiillee;;

if (theFileDidntClose && errorCode == 0)

errorCode = –4;

else errorCode = errorCode & –4;

else errorCode = –5;

return errorCode;

Για µια αναφορά σε άλλα σχεδιαστικά θέµατα που αφορούν την υλοποίηση του

µηχανισµού εξαιρέσεων µπορείτε να ανατρέξετε στην σελίδα 291 του [Horowitz

84]. Στην ίδια ενότητα µπορείτε να βρείτε µια περιγραφή εναλλακτικών τρόπων

υλοποίησης του µηχανισµού από τις γλώσσες PL/1, MESA, CLU και Ada. Για

µια περιληπτική περιγραφή του αντίστοιχου µηχανισµού της ML µπορείτε να

ανατρέξετε στο [Sethi 96]. Εµείς θα ασχοληθούµε στη συνέχεια µε τις κατασκευές

της Java µε τις οποίες η γλώσσα υποστηρίζει το χειρισµό των εξαιρέσεων.

™¯‹Ì· 8.2

Η κλασική διαχείριση

λαθών περιπλέκει τον

κώδικα.

Page 147: Γλώσσες Προγραμματισμού II

8.2 XÂÈÚÈÛÌfi˜ ÂÍ·ÈÚ¤ÛÂˆÓ ÛÙËÓ Java

8.2.1 µ·ÛÈΤ˜ ¤ÓÓÔȘ

Βασικοί στόχοι του µηχανισµού χειρισµού εξαιρέσεων της Java είναι:

• να επιτρέψει τη σύλληψη και διαχείριση των εξαιρέσεων,

• να επιτρέψει τη συγγραφή µεθόδων οι οποίες είναι σε θέση να ανιχνεύσουν

τις εµφανίσεις εξαιρετικών περιπτώσεων τις οποίες όµως, επειδή δεν είναι σε

θέση να αντιµετωπίσουν, πρέπει να µεταδώσουν στην καλούσα διαδικασία.

Για το δεύτερο στόχο διαθέτει κατασκευές που επιτρέπουν σε µια µέθοδο να

ανιχνεύσει µια εξαιρετική περίπτωση και να εγείρει µια εξαίρεση επιτρέπο-

ντας αλλά όχι επιβάλλοντας την αντιµετώπιση του εξαιρετικού συµβάντος

από τις καλούσες µεθόδους. Αναλυτικά στις κατασκευές αυτές θα αναφερ-

θούµε αργότερα. Προς το παρόν θα αναφέρουµε πως ένας µεγάλος αριθµός

µεθόδων του Java API ανιχνεύει και εγείρει εξαιρέσεις. Θα έχετε ήδη παρα-

τηρήσει πως πολλές από τις µεθόδους της βασικής βιβλιοθήκης έχουν στη

δήλωση τους τη λέξη κλειδί throws. Η throws ακολουθείται από µια λίστα

των ονοµάτων των τύπων των εξαιρέσεων που η µέθοδος µπορεί να εγείρει.

1 4 7X ∂ π ƒ π ™ ª √ ™ ∂ • ∞ π ƒ ∂ ™ ∂ ø ¡ ™ ∆ ∏ ¡ J AVA

∞ÓÙÈΛÌÂÓ· ∂Í·›ÚÂÛ˘

Μια εξαίρεση στη Java αναπαρίσταται από ένα αντικείµενο που δηµιουρ-

γείται τη στιγµή της αναγνώρισης της εξαίρεσης και είναι στιγµιότυπο µιας

απογόνου της κλάσης java.lang.Throwable της βασικής βιβλιοθήκης. H

κλάση Throwable έχει δύο απογόνους: την java.lang.Error και την

java.lang.Exception. Εξαιρέσεις που είναι απόγονοι της κλάσης Error προσ-

διορίζουν προβλήµατα σύνδεσης που σχετίζονται µε το δυναµικό φόρτωµα

(dynamic loading) ή προβλήµατα της ιδεατής µηχανής (virtual machine),

όπως έλλειψη µνήµης. Οι εξαιρέσεις αυτές, όπως και οι εξαιρέσεις που ανα-

παριστά η RuntimeExceptions, υποκλάση της Exceptions, στην πλειοψηφία

τους θεωρούνται µη αναστρέψιµες και δεν πρέπει να συλλαµβάνονται. Αντί-

θετα, εξαιρέσεις των υπόλοιπων απογόνων της Exception προσδιορίζουν συµ-

βάντα που µπορούν να αντιµετωπιστούν από το πρόγραµµα µε στόχο να ανα-

κτηθεί ο έλεγχος. Ο πίνακας που ακολουθεί παρουσιάζει παραδείγµατα τέτοι-

ων εξαιρέσεων και των γεγονότων που αυτές γνωστοποιούν.

Page 148: Γλώσσες Προγραμματισμού II

1 4 8 ∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡

Όταν κατά τη συγγραφή του σώµατος µιας µεθόδου Α καλέσουµε µια µέθο-

δο που εγείρει µια τουλάχιστο εξαίρεση, πρέπει να χειριστούµε την εξαίρε-

ση. Είναι βέβαια στην επιλογή µας να συλλάβουµε την εξαίρεση και να ενερ-

γήσουµε κατάλληλα µέσα στο σώµα της Α ή να την µεταβιβάσουµε στη

µέθοδο που θα καλέσει την Α. Ο κώδικας του σχήµατος 8.3 ζητά από το χρή-

στη να δώσει ένα αριθµό και στη συνέχεια τυπώνει το διπλάσιο του.

Η κλάση ExceptionTest χρησιµοποιεί για την εισαγωγή του αριθµού την

BufferedReader κλάση, στην τεκµηρίωση της οποίας θα πρέπει να ανα-

τρέξετε. Παρά το γεγονός ότι ο κώδικας φαίνεται σωστός, µια προσπάθεια

µεταγλώττισης θα µας δώσει την παρακάτω έξοδο:

Exception java.io.IOException must be caught, or it must be declared in

the throws clause of this method.

line = br.readline( );

^

Ο µεταγλωττιστής δηλαδή µας γνωστοποιεί ότι είτε πρέπει να συλλέξουµε

την εξαίρεση IOException είτε να την δηλώσουµε στο τµήµα throws της

µεθόδου.

Εξαίρεση Σηµατοδοτεί

java.io.EOFException προσπάθεια πρόσβασης µετά

το τέλος αρχείου

java.lang.ArrayAccessOutOfBound προσπάθεια αναφοράς σε

στοιχείο πίνακα έξω από

τα όρια του

java.lang.NumberFormatException µη αποδεκτό αριθµό

java.lang.ArithmeticException διαίρεση δια του µηδενός ή

modulo

Page 149: Γλώσσες Προγραμματισμού II

import java.io.*;

public class ExceptionTest

public static void main(String [] args)

int num;

num = getNumber();

System.out.println("To ‰ÈÏ¿ÛÈÔ ÙÔ˘ ·ÚÈıÌÔ‡ ›ӷÈ:"

+ 2 * num);

public static int getNumber()

String line;

BufferedReader br = new BufferedReader (new

InputStreamReader (System.in));

System.out.println("¢ÒÛÂ ¤Ó· ·ÚÈıÌfi:");

line = br.readLine();

return Integer.parseInt(line);

1 4 9X ∂ π ƒ π ™ ª √ ™ ∂ • ∞ π ƒ ∂ ™ ∂ ø ¡ ™ ∆ ∏ ¡ J AVA

™¯‹Ì· 8.3

Ο χειρισµός εξαιρέσεων

επιβάλλεται από

το σύστηµα.

8.2.2 ∏ ηٷÛ΢‹ try/catch/finally

Για τη σύλληψη µιας εξαίρεσης χρησιµοποιούµε ένα try µπλοκ. Το try µπλοκ,

το οποίο περικλείει τον κώδικα που µπορεί να εγείρει µια εξαίρεση, ακολου-

θείται προαιρετικά από ένα ή περισσότερα catch µπλοκ. Κάθε catch µπλοκ

προσδιορίζει τον τύπο της εξαίρεσης που µπορεί να συλλάβει και περιέχει

κώδικα για την αντιµετώπισή της. Μετά το τελευταίο catch µπλοκ ένα προ-

αιρετικό finally µπλοκ περιέχει κώδικα που επιθυµούµε να εκτελείται

πάντα ανεξάρτητα από το αν θα εγερθεί ή όχι µια εξαίρεση. Το finally

µπλοκ, αποτελεί ιδανική θέση για κώδικα που αποδίδει πόρους (cleanup code).

Το σχήµα 8.4 δίνει τη σύνταξη της πρότασης try/catch/finally.

Page 150: Γλώσσες Προγραμματισμού II

1 5 0 ∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡

ttrryy

// ÎÒ‰Èη˜ Ô˘ ÌÔÚ› Ó· ÂÁ›ÚÂÈ ÂÍ·›ÚÂÛË

ccaattcchh ((SSoommeeEExxcceeppttiioonn ee11))

// ÎÒ‰Èη˜ Ô˘ ¯ÂÈÚ›˙ÂÙ·È ÌÈ· ÂÍ·›ÚÂÛË e1 Ô˘ ›ӷÈ

// ÛÙÈÁÌÈfiÙ˘Ô Ù˘ ÎÏ¿Û˘ SomeException ‹

// ·ÔÁfiÓÔ˘ Ù˘.

ccaattcchh ((AAnnootthheerrEExxcceeppttiioonn ee22))

// ÎÒ‰Èη˜ Ô˘ ¯ÂÈÚ›˙ÂÙ·È ÌÈ· ÂÍ·›ÚÂÛË e2 Ô˘ ›ӷÈ

// ÛÙÈÁÌÈfiÙ˘Ô Ù˘ ÎÏ¿Û˘ AnotherException

// ‹ ·ÔÁfiÓÔ˘ Ù˘.

ffiinnaallllyy

// ÎÒ‰Èη˜ Ô˘ ÂÎÙÂÏÂ›Ù·È ¿ÓÙ·, ·ÓÂÍ¿ÚÙËÙ· ·fi ÙÔÓ

// ÙÚfiÔ Ì ÙÔÓ ÔÔ›Ô Ô ¤ÏÂÁ¯Ô˜ ‚Á‹Î ·fi ÙÔ try

// ÌÏÔÎ: ÏfiÁˆ ηÓÔÓÈÎÔ‡ ÙÂÚÌ·ÙÈÛÌÔ‡, ÂÍ ·ÈÙ›·˜

// ÌÈ·˜ ÚfiÙ·Û˘ break, continue ‹ return ‹ ÏfiÁˆ

// ¤ÁÂÚÛ˘ ÂÍ·›ÚÂÛ˘ Ë ÔÔ›· ›ÙÂ Û˘ÓÂÏ‹ÊıË ·fi ¤Ó·

// catch ÌÏÔΠ›Ù fi¯È,

™¯‹Ì· 8.4

Σύνταξη της πρότασης

try/catch/finally.

Όταν δηµιουργηθεί µια εξαίρεση στο try µπλοκ, ο µηχανισµός χειρισµού εξαι-

ρέσεων µεταφέρει τον έλεγχο έξω από το µπλοκ και αρχίζει την αναζήτηση του

κατάλληλου catch µπλοκ µε τη σειρά που αυτά εµφανίζονται. Ένα catch

µπλοκ είναι κατάλληλο, όταν η εγερθείσα εξαίρεση είναι στιγµιότυπο της κλά-

σης που ορίζει η παράµετρος του µπλοκ ή απογόνου της. Στην περίπτωση αυτή

ο έλεγχος µεταφέρεται στον κώδικα του catch µπλοκ. Εάν δεν εγερθεί εξαίρεση

από τον κώδικα του try µπλοκ τα catch µπλοκ παραλείπονται και ο έλεγχος

µεταφέρεται είτε στο finally µπλοκ, αν αυτό υπάρχει, είτε στην πρόταση που

ακολουθεί το τελευταίο catch. To finally µπλοκ δηλαδή, αν υπάρχει, εκτε-

λείται ανεξάρτητα από το αν εγερθεί ή όχι εξαίρεση ή αν αυτή συλληφθεί ή όχι.

Το γεγονός ότι δεν υπάρχει περίπτωση να φύγει ο έλεγχος από µια try πρόταση

χωρίς να εκτελεστεί το finally µπλοκ της, επιτρέπει τη χρήση της πρότασης

Page 151: Γλώσσες Προγραμματισμού II

try για να διασφαλίσουµε την εκτέλεση κώδικα απόδοσης πόρων σε περιπτώσεις χρήσης των προτάσεων

break, continue και return. Για ένα καλό παράδειγµα αυτής της χρήσης αλλά και για περισσότερες

λεπτοµέρειες για το finally µπλοκ µπορείτε να ανατρέξετε στην υπό ενότητα 7.4.1 του [Gosling 96].

Είναι εµφανές ότι ο µηχανισµός της Java δεν επιστρέφει τον έλεγχο µετά τον χειρισµό της εξαίρεσης

στο σηµείο που η εξαίρεση δηµιουργήθηκε (resumption model of exception handling), αλλά υιοθετεί το

termination model σύµφωνα µε το οποίο η εκτέλεση συνεχίζεται µε εκτέλεση του κώδικα που ακολου-

θεί τον κώδικα σύλληψης και αντιµετώπισης της εξαίρεσης.

1 5 1X ∂ π ƒ π ™ ª √ ™ ∂ • ∞ π ƒ ∂ ™ ∂ ø ¡ ™ ∆ ∏ ¡ J AVA

™˘ÌÂÚÈÊÔÚ¿ Java ÂÚÈ‚¿ÏÏÔÓÙÔ˜ Û ÂÚ›ÙˆÛË Ô˘ ÌÈ· ÂÍ·›ÚÂÛË ‰Â Û˘ÏÏËÊı›.

Η συµπεριφορά είναι διαφορετική στην περίπτωση που η εφαρµογή χρησιµοποιεί για την επικοινω-

νία της µε το χρήστη τη γραµµή διαταγών (command line) από ό,τι όταν αυτή χρησιµοποιεί γραφικό

περιβάλλον (GUI). Στην πρώτη περίπτωση, εάν µια εξαίρεση δε συλληφθεί, η εφαρµογή τερµατίζει

µετά την ενεργοποίηση ενός προκαθορισµένου (default) διαχειριστή εξαιρέσεων. Στη δεύτερη περί-

πτωση, στην οποία ανήκουν και τα java applets, ο χρήστης αποφασίζει για τον τερµατισµό ή όχι της

εφαρµογής ακόµη και µετά την ενεργοποίηση του προκαθορισµένου διαχειριστή εξαιρέσεων. Φυσι-

κά µετά την εµφάνιση της εξαίρεσης η εφαρµογή µπορεί να είναι σε ασυνεπή κατάσταση (inconsistent

state), που έχει σαν αποτέλεσµα απροσδιόριστη συµπεριφορά της.

Μπορεί να θεωρηθεί καλή επιλογή η χρήση catch µπλοκ που συλλαµβάνει

εξαίρεση τύπου Exception;

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘8.1

Εντοπίστε το σφάλµα στον τρόπο σύλληψης των εξαιρέσεων AException

και BException στον παρακάτω κώδικα, όταν ο τύπος BException είναι

απόγονος του AException.

class BadCatch

public void myMethod()

try

throw new BException(); // Ë ÚfiÙ·ÛË ÂÁ›ÚÂÈ

// ÌÈ· ÂÍ·›ÚÂÛË Ù‡Ô˘ BException

catch (AException ae)

….

(συνέχεια…)

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘8.2

Page 152: Γλώσσες Προγραμματισμού II

1 5 2 ∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡

8.2.3 ¶ÚÔÛı¤ÙÔÓÙ·˜ ¯ÂÈÚÈÛÌfi ÂÍ·ÈÚ¤ÛˆÓ

Ας επανέλθουµε τώρα στον κώδικα του σχήµατος 8.3 και ας επιχειρήσουµε

να κάνουµε τον κατάλληλο χειρισµό των εξαιρέσεων που εµφανίζουν οι

µέθοδοι readLine και parseInt των οποίων οι δηλώσεις έχουν ως ακολούθως:

public class Integer extends Number

….

public static int parseInt(String s) throws

NumberFormatException

public class BufferedReader extends Reader

public String readLine() throws IOException

….

Για να χρησιµοποιήσουµε µια µέθοδο Α που εγείρει εξαιρέσεις θα πρέπει

είτε να συλλάβουµε τις εξαιρέσεις ή µια πρόγονο κλάση τους όπως στον

κώδικα του σχήµατος 8.5, είτε να δηλώσουµε τη µέθοδο µέσα στην οποία

καλούµε την Α, έτσι ώστε να µεταδίδει τις εξαιρέσεις, όπως στον κώδικα

του σχήµατος 8.6.

(…συνέχεια)

catch(BException be)

….

Page 153: Γλώσσες Προγραμματισμού II

import java.io.*;

public class ExceptionTest1

public static void main(String [] args)

int num = getNumber();

System.out.println("To ‰ÈÏ¿ÛÈÔ ÙÔ˘ ·ÚÈıÌÔ‡

›ӷÈ:" + 2 * num);

public static int getNumber()

String line;

BufferedReader br = new BufferedReader (new

InputStreamReader (System.in));

System.out.println("¢ÒÛÂ ¤Ó· ·ÚÈıÌfi:");

ttrryy

line = br.readLine(); //readLine throws

//IOException

return Integer.parseInt(line); //parseInt throws

//NumberFormatExc

//eption

ccaattcchh((ππ√√EExxcceeppttiioonn ee))

System.out.println(e);

ccaattcchh((NNuummbbeerrFFoorrmmaattEExxcceeppttiioonn ee))

System.out.println(e);

return 0;

1 5 3X ∂ π ƒ π ™ ª √ ™ ∂ • ∞ π ƒ ∂ ™ ∂ ø ¡ ™ ∆ ∏ ¡ J AVA

™¯‹Ì· 8.5

Οι εξαιρέσεις συλλαµβά-

νονται από τη µέθοδο.

Page 154: Γλώσσες Προγραμματισμού II

1 5 4 ∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡

import java.io.*;

public class ExceptionTest2

public static void main(String [] args)

ttrryy

int num = getNumber(); // throws Exception

System.out.println("To ‰ÈÏ¿ÛÈÔ ÙÔ˘ ·ÚÈıÌÔ‡ ›ӷÈ:" + 2 * num);

ccaattcchh((ππ√√EExxcceeppttiioonn ee))

System.out.println(e);

ccaattcchh((NNuummbbeerrFFoorrmmaattEExxcceeppttiioonn ee))

System.out.println(e);

public static int getNumber() tthhrroowwss EExxcceeppttiioonn

String line;

BufferedReader br = new BufferedReader (new InputStreamReader

(System.in));

System.out.println("¢ÒÛÂ ¤Ó· ·ÚÈıÌfi:");

line = br.readLine();// readLine throws IOException

return Integer.parseInt(line); //parseInt throws NumberFormatException

™¯‹Ì· 8.6

Αν οι εξαιρέσεις δεν συλ-

λαµβάνονται, η µέθοδος

πρέπει να τις µεταδίδει.

Στη δεύτερη περίπτωση είναι προφανές ότι η ευθύνη για χειρισµό των εξαι-

ρέσεων περνάει τώρα στη main. Έτσι, η main συλλαµβάνει την εξαίρεση

Exception που είναι πρόγονος των IOException και NumberFormat

Exception.

8.2.4 ¢‹ÏˆÛË Ù‡ˆÓ ÂÍ·›ÚÂÛ˘

Όπως ήδη αναφέραµε οι εξαιρέσεις στην Java είναι αντικείµενα. Κάθε τύπος

εξαίρεσης αναπαρίσταται από µια κλάση που κληρονοµεί από σύµβαση την

κλάση Exception ή κάποια από τις απογόνους της, παρότι θα µπορούσε να

κληρονοµεί απευθείας την κλάση Throwable. Η Throwable περιέχει ένα

αλφαριθµητικό, το οποίο χρησιµοποιείται για την αποθήκευση µιας κατα-

νοητής από τον χρήστη περιγραφής της εξαίρεσης. Επειδή η περιγραφή αυτή

δεν είναι πάντα αρκετή για να περιγράψει την εξαίρεση, η κλάση Exception

Page 155: Γλώσσες Προγραμματισμού II

επεκτείνεται για να δηµιουργηθεί µια νέα κλάση που περιέχει τα επιπλέον

δεδοµένα, τα οποία συνήθως παίρνουν αρχική τιµή από το δηµιουργό της.

Σαν παράδειγµα θα θεωρήσουµε µια µέθοδο που δέχεται σαν πρώτο όρισµα

ένα όνοµα κατηγορήµατος (attribute) την τιµή του οποίου θα αντικαταστή-

σει µε το δεύτερο όρισµα που είναι µια νέα τιµή. Αν το κατηγόρηµα δεν

υπάρχει πρέπει να εγερθεί µια εξαίρεση. Η κλάση που θα αναπαριστά την

εξαίρεση µπορεί να περιέχει µια αναφορά σε αλφαριθµητικό, που θα ενηµε-

ρωθεί µε το όνοµα του κατηγορήµατος και µια αναφορά σε Object που θα

ενηµερωθεί µε τη νέα τιµή. Οι τιµές των δυο αυτών κατηγορηµάτων θα χρη-

σιµοποιηθούν και για την ενηµέρωση του αλφαριθµητικού της κλάσης

Throwable. Έτσι ο κώδικας διαµορφώνεται όπως στο σχήµα 8.7.

public class NoSuchAttributeException extends Exception

public String attrName;

public Object newValue;

NosuchAttributeException(String name, Object value)

super("¢ÂÓ ˘¿Ú¯ÂÈ Î·ÙËÁfiÚËÌ· Ì fiÓÔÌ· \" + "name");

attrName = name;

newValue = value;

Παρατηρήστε πώς ο δηµιουργός καλεί µε τη χρήση της super, τον δηµιουρ-

γό της κλάσης Exception αποδίδοντας τιµή στο αλφαριθµητικό. Είναι

εµφανές ότι αυτός ο τύπος της εξαίρεσης είναι πιο χρήσιµος στον κώδικα

που αντιµετωπίζει την εξαίρεση, γιατί αφενός περιέχει ένα αναγνωρίσιµο από

τον άνθρωπο αλφαριθµητικό, αφετέρου δε περιέχει και τα δεδοµένα που προ-

κάλεσαν την εξαίρεση. Η τελευταία αυτή πληροφορία είναι άµεσα προσβά-

σιµη στον κώδικα που αντιµετωπίζει την εξαίρεση.

8.2.5 ŒÁÂÚÛË ÂÍ·›ÚÂÛ˘

Όπως είπαµε, όταν αναγνωρισθεί µια εξαιρετική κατάσταση, εγείρεται µια

εξαίρεση. Η έγερση µιας εξαίρεσης γίνεται δηµιουργώντας µια πρόταση

throw. Η πρόταση αποτελείται από τη λέξη–κλειδί throw ακολουθούµενη

1 5 5X ∂ π ƒ π ™ ª √ ™ ∂ • ∞ π ƒ ∂ ™ ∂ ø ¡ ™ ∆ ∏ ¡ J AVA

™¯‹Ì· 8.7

Ορισµός κλάσης για

αναπαράσταση τύπου

εξαίρεσης.

Page 156: Γλώσσες Προγραμματισμού II

1 5 6 ∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡

από την αναφορά ενός στιγµιότυπου της κλάσης που αναπαριστά τον τύπο

της εξαίρεσης. H πρόταση

throw new NosuchAttributeException(name, value);

εγείρει µια εξαίρεση τύπου NosuchAttributeException.

Εναλλακτικά µια εξαίρεση εγείρεται απλά καλώντας µια µέθοδο που εγείρει

τη συγκεκριµένη εξαίρεση. Ο µεταγλωττιστής της Java επιβάλει την αναφορά

των εξαιρέσεων, οι οποίες εγείρονται σε µία µέθοδο και δεν συλλαµβάνονται

από catch µπλοκς, στο τµήµα throws της δήλωσης της. Οι εξαιρέσεις που εγεί-

ρει µια µέθοδος είναι εξίσου σηµαντικές µε τον τύπο της επιστρεφόµενης τιµής

της µεθόδου και έτσι αποτελούν µέρος της διεπαφής της µεθόδου.

Αποφεύγετε να χαρακτηρίζετε απλές αναµενόµενες[1] καταστάσεις σαν εξαι-

ρέσεις. Για παράδειγµα, η αναγνώριση του τέλους ενός stream εισόδου είναι

αναµενόµενο συµβάν και εποµένως µέρος της αναµενόµενης συµπεριφοράς

της µεθόδου που διαβάζει ένα stream και είναι η προκύπτουσα από το γεγο-

νός «έφτασε το τέλος». Ανατρέξτε στην ενότητα 7.5 του [Gosling 96] για

σχολιασµό του θέµατος και ένα καλό παράδειγµα.

[1] ∆υστυχώς οι κανόνες προσδιορισµού µιας κατάστασης σαν αναµενόµενης ή όχι

δεν είναι σαφείς.

Πώς εγείρονται εξαιρέσεις στην Java;ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

8.3

Θεωρήστε τη µέθοδο pop της κλάσης Stack. Η µέθοδος επιστρέφει το

τελευταίο εισαχθέν αντικείµενο. Περιγράψτε µε φυσική γλώσσα τις απα-

ραίτητες ενέργειες για την αντιµετώπιση της περίπτωσης της µη ύπαρξης

αντικειµένου στη στοίβα.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

8.4

Θεωρήστε την άσκηση αυτοαξιολόγησης 1. ∆ώστε σε java τον κώδικα της

pop που αναγνωρίζει και χειρίζεται την εξαίρεση «άδεια στοίβα».

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

8.5

Page 157: Γλώσσες Προγραμματισμού II

1 5 7X ∂ π ƒ π ™ ª √ ™ ∂ • ∞ π ƒ ∂ ™ ∂ ø ¡ ™ ∆ ∏ ¡ J AVA

Αν η µέθοδος myMethod καλεί την pop, τι θα πρέπει να προσέξουµε στη

δήλωση και τον ορισµό της;

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘8.6

Προσδιορίστε την έξοδο που προκύπτει από την εκτέλεση της µεθόδου

myMethod της οποίας ο κώδικας δίνεται στη συνέχεια.

static void myMethod(String myString)

System.out.println("myMethod Begin");

try

if(myString.equals("klea"))

System.out.println("∆Ô ·ÏÊ·ÚÈıÌËÙÈÎfi

‚Ú¤ıËÎÂ");

catch(NullPointerException npe)

System.out.println("NullPointerException

Û˘ÓÂÏ‹ÊıË");

System.out.println("NullPointerException

·ÓÙÈÌÂÙˆ›ÛÙËÎÂ");

catch(Exception e)

System.out.println("ÌÈ· ÌË ·Ó·ÌÂÓfiÌÂÓË ÂÍ·›ÚÂÛË

Û˘ÓÂÏ‹ÊıË");

System.out.println("Ë ÂÍ·›ÚÂÛË ‰ÂÓ

·ÓÙÈÌÂÙˆ›ÛÙËÎÂ");

throw e;

finally

System.out.println("Ù¤ÏÔ˜ ‰È·¯ÂÈÚÈÛÙ‹ ÂÍ·ÈÚ¤ÛˆÓ");

System.out.println("myMethod End");

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘8.7

Page 158: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 8 : X ∂ π ƒ π ™ ª √ ™ E • ∞ π ƒ ∂ ™ ∂ ø ¡1 5 8

Εντοπίστε το λάθος στη δήλωση της κλάσης myMethod της άσκησης Αυτο-

αξιολόγησης 8.7.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

8.8

Θεωρήστε τη µέθοδο myMethod, όπως δόθηκε από την άσκηση αυτοαξιο-

λόγησης 8.7 και διαµορφώθηκε από την 8.8. Γράψτε ένα µικρό πρόγραµ-

µα µε το οποίο θα επιδεικνύετε τις διαφορετικές εξόδους της myMethod.

¢Ú·ÛÙËÚÈfiÙËÙ·8.1

™‡ÓÔ„Ë

Η αντιµετώπιση των εξαιρετικών περιπτώσεων, όπως την υποστηρίζει η C

και η Pascal, µε επιστρεφόµενες τιµές λάθους ή µε ενηµέρωση γενικών µετα-

βλητών δηµιουργεί πολλά προβλήµατα και αυξάνει την πολυπλοκότητα του

πηγαίου κώδικα. Οι σύγχρονες γλώσσες προγραµµατισµού υιοθέτησαν την

τεχνική της διαχείρισης εξαιρέσεων σύµφωνα µε την οποία µια εξαίρεση ανα-

γνωρίζεται, εγείρεται, συλλαµβάνεται και αντιµετωπίζεται κατάλληλα. Η

τεχνική χειρισµού εξαιρέσεων έχει σαν αποτέλεσµα την αύξηση της ευρω-

στίας και αξιοπιστίας των προγραµµάτων, καθώς και της ευκρίνειας του

πηγαίου κώδικα.

Η Java υποστηρίζει την τεχνική χειρισµού εξαιρέσεων κύρια µε την πρόταση

try/catch/finally. To try µπλοκ περιβάλλει τον κώδικα που µπορεί να εγείρει

µια εξαίρεση, ενώ κάθε catch µπλοκ περιέχει τον κώδικα για την αντιµετώ-

πιση συγκεκριµένου τύπου εξαίρεσης. Το finally µπλοκ περιέχει κώδικα

κυρίως για απόδοση πόρων. Η πρόταση throws χρησιµοποιείται για τη δηµι-

ουργία ενός αντικειµένου εξαίρεσης το οποίο λέµε ότι εγείρεται. Εξαιρέσεις

που δε συλλαµβάνονται από catch µπλοκ πρέπει να δηλώνονται στη διεπαφή

της µεθόδου αποτελώντας κατ’ αυτό τον τρόπο αναπόσπαστο µέρος της. Λέµε

ότι η µέθοδος εγείρει τις συγκεκριµένες εξαιρέσεις, γεγονός που επιβάλει την

κλήση της µεθόδου µόνο µέσα σε try µπλοκ.

Η Java έχει ορισµένο έναν αριθµό κλάσεων εξαιρέσεων µε βασική (root) την

Throwable. Κάθε εξαίρεση οριζόµενη από το χρήστη, αν και µπορεί να κλη-

ρονοµεί άµεσα τη Throwable, κληρονοµεί από σύµβαση την Exception. Οι

υποκλάσεις Error και RuntimeException της Throwable αποτελούν εξαιρέ-

σεις των οποίων η σύλληψη δεν ελέγχεται από το µεταγλωττιστή.

Page 159: Γλώσσες Προγραμματισμού II

BÈ‚ÏÈÔÁÚ·Ê›·

[1] [Anuff 96]

Anuuf Ed, «The Java Sourcebook» John Wiley and Sons Inc. 1996.

[2] [[Deitel 98]

Deitel & Deitel «Java: How to program», Second edition, Prentice Hall

International 1998.

[3] [[Gosling 96]

Ken Arnold, James Gosling, «The Java Programming Language»,

Addison Wesley, 1996.

[4] [[Horowitz 84]

«Βασικές αρχές γλωσσών προγραµµατισµού» Εκδόσεις Κλειδάριθµος

1993.

Το βιβλίο είναι µετάφραση της δεύτερης Αµερικάνικης έκδοσης του

Ellis Horowitz «Fundamentals of Programming Languages», Computer

Science Press, 1984. Αποτελεί µια πολύ καλή και, κατά τα γνωστά µου,

µοναδική στην Ελληνική γλώσσα, πηγή αναφορικά µε τις βασικές αρχές

των γλωσσών προγραµµατισµού. Το βιβλίο είναι κατάλληλο για ανά-

γνωση µόνο επιλεκτικών τµηµάτων από σπουδαστές που µαθαίνουν την

πρώτη τους γλώσσα προγραµµατισµού. Είναι όµως απαραίτητο για

σπουδαστές που γνωρίζουν και έχουν χρησιµοποιήσει εκτεταµένα µια

τουλάχιστο γλώσσα προγραµµατισµού.

[5] [[Sethi 97]

Ravi Sethi, «Programming Languages: Concepts and Constructs» 2nd

Edition, Addison Wesley 1996. Reprinted with corrections April 1997.

1 5 9B I B § I O ° PA º I A

Page 160: Γλώσσες Προγραμματισμού II
Page 161: Γλώσσες Προγραμματισμού II

T·˘Ùfi¯ÚÔÓÔ˜ ¶ÚÔÁÚ·ÌÌ·ÙÈÛÌfi˜

™ÎÔfi˜

Σκοπός του κεφαλαίου είναι να εισάγει τις βασικές έννοιες του ταυτόχρονου

προγραµµατισµού και του τρόπου που αυτός επιτυγχάνεται στο αντικειµενο-

στρεφές στύλ προγραµµατισµού.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• περιγράψετε τον όρο νήµα ελέγχου (thread of control),

• δηµιουργείτε πολυ–νηµατικές εφαρµογές,

• αναφέρετε τις κατασκευές της Java που υποστηρίζουν τον ταυτόχρονο προ-

γραµµατισµό,

• περιγράψετε το πρόβληµα του αµοιβαίου αποκλεισµού,

• περιγράψετε το αφαιρετικό πρόβληµα του παραγωγού–καταναλωτή,

• δίνετε µε Java λύση σε προβλήµατα παραγωγού–καταναλωτή.

ŒÓÓÔȘ ÎÏÂȉȿ

• νήµα (thread)

• πολυ–νηµατικό (multithreaded)

• σηµατοφόρος (semaphore)

• ελεγκτής (monitor)

• κρίσιµος τοµέας

• πρόβληµα παραγωγού–

καταναλωτή

• µεταβλητή συνθήκης ελεγκτή

(monitor’s condition variable)

• Runnable interface

• προτεραιότητα νήµατος

9∫ ∂ º ∞ § ∞ π √

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Αν έτυχε να χρησιµοποιήσετε έναν επεξεργαστή κειµένου µερικά χρόνια πριν

θα προσέξατε ότι, όταν του αναθέτατε να εκτελέσει µια χρονοβόρο εργασία,

όπως για παράδειγµα εκτύπωση, έπρεπε να περιµένετε να ολοκληρωθεί η εργα-

σία αυτή και µετά να συνεχίσετε µε κάποια άλλη. Αυτό οφείλεται στη βασική

Page 162: Γλώσσες Προγραμματισμού II

1 6 2 ∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™

υπόθεση που κάναµε µέχρι τώρα ότι, όταν εκτελούµε ένα πρόγραµµα µόνο µια

ακολουθία εντολών εκτελείται σε δεδοµένο χρονικό διάστηµα. Στην περίπτω-

ση αυτή λέµε πως η εφαρµογή έχει ένα thread[1] ελέγχου (thread of control).

Αντίθετα, όπως θα έχετε παρατηρήσει, ένας σύγχρονος κειµενογράφος έχει

τη δυνατότητα να εκτελεί ταυτόχρονα περισσότερες της µίας διεργασίες. Μας

επιτρέπει, για παράδειγµα, να συνεχίζουµε την επεξεργασία του κειµένου, ενώ

εκτελεί ταυτόχρονα τη διεργασία της εκτύπωσης. Λέµε τότε, πως η εφαρµο-

γή είναι πολυ–νηµατική (multithreaded).

Σήµερα, όλο και µεγαλύτερος αριθµός εφαρµογών, κυρίως πραγµατικού χρό-

νου, επιβάλει την υλοποίησή τους µε τη µορφή πολυ–νηµατικών εφαρµογών.

Η υποστήριξη του συγχρονισµού και της επικοινωνίας στον ταυτόχρονο προ-

γραµµατισµό υιοθετήθηκε από λίγες σχετικά γλώσσες προγραµµατισµού. Πριν

λίγα χρόνια αυτό ήταν σχεδόν αποκλειστικό προνόµιο των λειτουργικών

συστηµάτων.

Το κεφάλαιο είναι οργανωµένο σε τρεις ενότητες. Στην πρώτη από αυτές γίνε-

ται µια πολύ σύντοµη εισαγωγή στις βασικές έννοιες του ταυτόχρονου προ-

γραµµατισµού. Στη δεύτερη ενότητα περιγράφεται η κλάση Thread, πάνω στην

οποία η Java βασίζει την υποστήριξη του ταυτόχρονου προγραµµατισµού.

Γίνεται αναφορά στον κύκλο ζωής ενός νήµατος και στο θέµα του συγχρονι-

σµού µεταξύ νηµάτων της ίδιας εφαρµογής. Τέλος, η τρίτη ενότητα χρησιµο-

ποιεί ένα από τα κλασικά παραδείγµατα της βιβλιογραφίας, το πρόβληµα του

παραγωγού και του καταναλωτή, για να εισάγει τον τρόπο που η Java υπο-

στηρίζει το συγχρονισµό νηµάτων.

Το κεφάλαιο θέλει ιδιαίτερη προσοχή, καθώς εισάγει σύνθετες έννοιες. Η

δυσκολία έγκειται αφενός µεν στη φύση των εννοιών, αφετέρου δε στο σύν-

θετο των κατασκευών µε τις οποίες οι γλώσσες προγραµµατισµού τις υπο-

στηρίζουν. Σας συνιστώ να δώσετε ιδιαίτερη έµφαση στην εκτέλεση των παρα-

δειγµάτων και των ασκήσεων που χρησιµοποιούνται καθ’ όλη τη διάρκεια

του κεφαλαίου.

[1] O Ελληνικός όρος που έχει επικρατήσει για το thread είναι «νήµα». Ένα νήµα

ελέγχου είναι µια ακολουθία προτάσεων που εκτελούνται η µία µετά την άλλη.

Page 163: Γλώσσες Προγραμματισμού II

∆·˘ÙÔ¯ÚÔÓÈÛÌfi˜ ÛÙÔ «fast–food o °ÈÒÚÁÔ˜»

Θυµόσαστε το παράδειγµα «Fast–food ο Γιώργος» του πρώτου κεφαλαίου.

Το σύστηµα, το fast–food, αποτελείται από ένα σύνολο από αντικείµενα, τα

οποία συνεργάζονται µεταξύ τους για την παροχή υπηρεσιών προς τον έξω

κόσµο. Τη φιλοσοφία αυτή υιοθετήσαµε για την ανάπτυξη της Αριθµοµηχα-

νής του κεφαλαίου 7. Ορίσαµε την αριθµοµηχανή µας σαν µια συνάθροιση

αντικειµένων, τα οποία συνεργάζονται (collaborate) µεταξύ τους για να υπο-

λογίσουν την τιµή της έκφρασης που δηµιούργησε ο χρήστης. Υπάρχει όµως

µια πολύ βασική διαφορά. Το fast–food µπορεί και εξυπηρετεί ταυτόχρονα

πολλούς πελάτες αντίθετα µε την Αριθµοµηχανή που εξυπηρετεί µόνο έναν.

Σχεδόν κάθε αντικείµενο του fast–food µπορεί να δρα ταυτόχρονα µε τα άλλα

αντικείµενα. Η Μαίρη έστειλε ένα µήνυµα στο φούρνο µικροκυµάτων για να

ζεστάνει την τυρόπιτα και συνέχισε µε κάποια άλλη δραστηριότητα της. Την

ίδια χρονική στιγµή ο Γιώργος παίρνει την παραγγελία από τον επόµενο πελά-

τη. Λέµε ότι τα τρία αντικείµενα δρουν ταυτόχρονα. Αυτό δε συµβαίνει στην

Αριθµοµηχανή που αναπτύξαµε, γιατί ένα αντικείµενο της είναι ενεργό µόνο

όταν έχει αποκλειστική χρήση του επεξεργαστή. Και καθώς το σύστηµα µας

έχει έναν επεξεργαστή, µόνο ένα αντικείµενο µπορεί να είναι ενεργό ανά πάσα

χρονική στιγµή. Όταν το αντικείµενο αυτό αποστείλει ένα µήνυµα σ’ ένα άλλο

αντικείµενο, του «περνάει» µαζί και τον έλεγχο. Το αντικείµενο παραλήπτης

ολοκληρώνει τη δράση του και επιστρέφει τον έλεγχο στον αποστολέα.

Τα πολύπλοκα σηµερινά συστήµατα απαιτούν την ταυτόχρονη δράση

περισσότερων αντικειµένων. Σε µια εφαρµογή που φορτώνει ένα video clip

από το δια–δίκτυο σίγουρα δεν θέλουµε να περιµένουµε να ολοκληρωθεί

το φόρτωµα και µετά να αρχίσει η προβολή του. Το αντικείµενο που παρέ-

χει την υπηρεσία της προβολής δρα ταυτόχρονα µε αποτέλεσµα να έχουµε

προβολή του video πριν ολοκληρωθεί το φόρτωµα του.

Aς δούµε τώρα το παρακάτω σηµαντικό πρόβληµα που είναι πολύ πιθανό

να συναντήσετε σε µια εφαρµογή µε δύο ή περισσότερα νήµατα ελέγχου.

Αν δύο διαφορετικά νήµατα ελέγχου Ν1 και Ν2 θέλουν να χρησιµοποιή-

σουν για παράδειγµα τη στοίβα και καλέσουν ταυτόχρονα τις µεθόδους

push και pop αντίστοιχα, η τεχνική του time–slicing θα δηµιουργήσει πρό-

βληµα, καθώς οι πρωτογενείς ενέργειες της pop θα παρεµβληθούν χρονι-

κά στις αντίστοιχες ενέργειες της push (interleaving). H παρεµβολή αυτή,

(συνέχεια…)

1 6 3∂ π ™ ∞ ° ø ° π ∫ ∂ ™ ¶ ∞ ƒ∞∆ ∏ ƒ ∏ ™ ∂ π ™

Page 164: Γλώσσες Προγραμματισμού II

1 6 4 ∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™

9.1 B·ÛÈΤ˜ ¤ÓÓÔȘ Ù·˘Ùfi¯ÚÔÓÔ˘ ÚÔÁÚ·ÌÌ·ÙÈÛÌÔ‡

Ο ταυτόχρονος προγραµµατισµός (concurrent programming) είναι ένα

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

νει ένα σύνολο από τεχνικές και εργαλεία για τη διαχείριση παράλληλα

εκτελούµενων διεργασιών. Οι διαιτητές µνήµης (memory arbiters), οι

σηµατοφόροι (semaphores), οι ελεγκτές (monitors) και τα ραντεβού

(randezvous) είναι πολύτιµα εργαλεία στη διάθεση του προγραµµατιστή

για να αντιµετωπίσει µε επιτυχία την ανάπτυξη συστηµάτων πραγµατικού

χρόνου και ιδιαίτερα τις αυστηρές απαιτήσεις αξιοπιστίας που η φύση των

συστηµάτων αυτών επιβάλλει.

Θα πρέπει να διευκρινίσουµε ότι ο ταυτόχρονος προγραµµατισµός είναι ανε-

ξάρτητος από την υλοποίηση της παραλληλίας στα υπολογιστικά συστήµα-

τα. Η υλοποίηση αυτή µπορεί να γίνεται είτε σε επίπεδο υλικού, µε χρήση

περισσότερων του ενός επεξεργαστών,είτε σε επίπεδο λογισµικού µε εφαρ-

µογή της τεχνικής καταµερισµού χρόνου (time–slicing). Ένας επεξεργαστής

µε την τεχνική αυτή δηµιουργεί τη ψευδαίσθηση ότι εκτελούνται ταυτόχρο-

να περισσότερες από µια διεργασίες.

Ο ταυτόχρονος προγραµµατισµός προσφέρει ένα αφαιρετικό περιβάλλον

µέσα στο οποίο µπορεί να µελετηθεί η παραλληλία, δίνοντας έµφαση στην

ουσία και απαλλάσσοντας τον προγραµµατιστή από τις λεπτοµέρειες της

(…συνέχεια)

αν και σε πολλές περιπτώσεις είναι αποδεκτή, θα δηµιουργήσει προβλή-

µατα. Ο κατασκευαστής του φούρνου µικροκυµάτων αντιµετώπισε το πρό-

βληµα αυτό προσθέτοντας ένα λαµπάκι µε το οποίο ο φούρνος γνωστοποιεί

στους υποψήφιους πελάτες του, αν είναι διαθέσιµος ή όχι. ∆εν επιτρέπεται

σ’ έναν πελάτη να χρησιµοποιήσει το φούρνο µικροκυµάτων αν αυτός

παρέχει µια υπηρεσία σ’ έναν άλλο πελάτη. Ο Νίκος θα πρέπει να περιµέ-

νει σε µια ουρά όπου θα µπαίνουν όσοι επιθυµούν να χρησιµοποιήσουν το

φούρνο. Με την ίδια λογική και ο Adder, αν προσπαθήσει να χρησιµοποι-

ήσει τη στοίβα, όταν αυτή χρησιµοποιείται από άλλο αντικείµενο, θα πρέ-

πει να µπει σε µια ουρά αναµονής. Η διαφορά είναι όµως ότι µόλις ελευ-

θερωθεί ο πόρος (φούρνος–στοίβα), ο µεν Νίκος θα µπορέσει να το χρησι-

µοποιήσει αµέσως, ο Adder όµως θα το χρησιµοποιήσει µόνο αν εξασφα-

λίσει ταυτόχρονα και χρόνο από τον επεξεργαστή.

Page 165: Γλώσσες Προγραμματισμού II

υλοποίησης. Πρωταρχικό βήµα βέβαια για τη συγγραφή ενός προγράµµα-

τος, που θα αποτελείται από πολλές διεργασίες που θα τρέχουν παράλληλα,

είναι η αναγνώριση των διεργασιών αυτών. Στη συνέχεια θα πρέπει να γίνει

η αναπαράσταση αυτών των διεργασιών µε τους µηχανισµούς της γλώσσας

και να αντιµετωπιστεί το θέµα της µεταξύ τους επικοινωνίας.

Το πρόβληµα του αµοιβαίου αποκλεισµού (mutual exclusion) αποτελεί το

υπ’ αριθµόν ένα πρόβληµα του ταυτόχρονου προγραµµατισµού. Το πρό-

βληµα δηµιουργείται, όταν πολλές διεργασίες ανταγωνίζονται για τη χρήση

κάποιου συγκεκριµένου πόρου (δες στοίβα – φούρνος µικροκυµάτων), η

φύση του οποίου όµως επιβάλει τη χρήση του από µια µόνο διεργασία κάθε

φορά. Η χρήση δηλαδή του πόρου από µια διεργασία αποκλείει την ταυτό-

χρονη χρήση της από άλλη. Για µια πολύ καλή παραστατική παρουσίαση των

προσπαθειών για την επίλυση του προβλήµατος του αµοιβαίου αποκλεισµού,

µε πιο γνωστή αυτή που εκφράζεται από τον αλγόριθµο του Dekker, µπο-

ρείτε να ανατρέξετε στο κεφάλαιο 3 του [Ben 97].

1 6 5B ∞ ™ π ∫ ∂ ™ ∂ ¡ ¡ √ π ∂ ™ ∆∞ À ∆ √ à ƒ √ ¡ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À

™ËÌ·ÙÔÊfiÚÔ˜

Ο σηµατοφόρος που εισήχθη από τον Dikjstra [Dijkstra 68] αποτελεί ένα

από τα πρωτογενή στοιχεία συγχρονισµού διεργασιών. Αποτελεί µάλιστα

ένα από τα πιο αγαπητά εργαλεία για την έκφραση κοµψών λύσεων σε

ενδιαφέροντα προβλήµατα. Ένας σηµατοφόρος s είναι µια κατασκευή που

έχει µια ακέραια µεταβλητή value και υποστηρίζει δύο λειτουργίες:

wait(s) που συµβολίζεται και σαν p(s): Όταν µια διεργασία προσπαθεί να

αποκτήσει πρόσβαση στο σηµατοφόρο και ισχύει value > 0, τότε µειώνε-

ται η τιµή της value κατά 1 και η διεργασία αναλαµβάνει τον έλεγχο της

εκτέλεσης. Αλλιώς, η διεργασία που την επιχειρεί αναστέλλει την εκτέλε-

σή της έως ότου η τιµή της value γίνει µεγαλύτερη ή ίση µε 1.

signal(s) που συµβολίζεται και σαν v(s): Αν κάποια διεργασία έχει ανα-

στείλει την εκτέλεση της από µια προηγούµενη κλήση της wait στον ίδιο

σηµατοφόρο s, αφυπνίζεται, αλλιώς η τιµή της value αυξάνεται κατά 1.

Για µια επίλυση του προβλήµατος του αµοιβαίου αποκλεισµού µε χρήση

σηµατοφόρων και ανεξάρτητης γλώσσας προγραµµατισµού, µπορείτε να

ανατρέξετε στην ενότητα 4.2 του [Ben 97].

Page 166: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™1 6 6

Κρίσιµος τοµέας

Ένας κρίσιµος τοµέας (critical section) ενός αντικειµένου, είναι ένα τµήµα

κώδικα που πρέπει να εκτελείται µε τρόπο, που να αποκλείει την εκτέλεση

όλων των άλλων κρίσιµων τοµέων του ίδιου αντικειµένου.

Ελεγκτές

Οι ελεγκτές (monitors) αποτελούν µια αφαιρετική έννοια, υψηλότερου επι-

πέδου από τους κρίσιµους τοµείς και τους σηµατοφόρους. Ένας ελεγκτής,

ενθυλακώνει τα κοινά δεδοµένα σε µια κατασκευή που καλείται monitor.

Ένα αντικείµενο monitor, είναι µια συλλογή από διαµοιραζόµενες (shared)

µεταβλητές και µεθόδους µε τον περιορισµό, ότι απαγορεύεται η εκτέλε-

ση µιας monitor µεθόδου από δύο διαδικασίες ταυτόχρονα. Για µια σύντο-

µη αναφορά στην κατασκευή του ελεγκτή, µπορείτε να ανατρέξετε στο

[Sethi 97], ενώ για µια πιο αναλυτική στο κεφάλαιο 5 του [Ben 97].

Page 167: Γλώσσες Προγραμματισμού II

9.2 YÔÛÙ‹ÚÈÍË Ù·˘Ùfi¯ÚÔÓÔ˘ ÚÔÁÚ·ÌÌ·ÙÈÛÌÔ‡ ·fi ÙËÓ Java

™ÎÔfi˜

Σκοπός της ενότητας είναι να εισάγει τις κατασκευές της Java, οι οποίες υπο-

στηρίζουν τη διαδικασία της δηµιουργίας πολυ–νηµατικών εφαρµογών.

¶ÚÔÛ‰ÔÎÒÌÂÓ· ∞ÔÙÂϤÛÌ·Ù·

Όταν θα έχετε ολοκληρώσει το κεφάλαιο αυτό θα µπορείτε να:

• δηµιουργείτε τα δικά σας νήµατα χρησιµοποιώντας την κλάση Thread,

• περιγράψετε τις καταστάσεις ενός νήµατος ελέγχου,

• ενεργοποιήσετε, τερµατίσετε, βάλετε σε αναµονή ή σε ανάπαυση ένα νήµα

ελέγχου,

• χρησιµοποιήσετε την πρόταση synchronized της Java.

ŒÓÓÔȘ ÎÏÂȉȿ

1 6 7Y ¶ √ ™ ∆ ∏ ƒ π • ∏ ∆∞ À ∆ √ à ƒ √ ¡ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À ∞ ¶ √ ∆ ∏ ¡ J AVA

• κλάση Thread

• sleep

• notify

• notifyAll

• wait

• yield

• synchronized

• προτεραιότητα νήµατος

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Η Java παρέχει πλήρη υποστήριξη των νηµάτων µε ειδικές κατασκευές, αλλά

και µε κατάλληλες κλάσεις της βασικής βιβλιοθήκης της. Η κλάση Thread

χρησιµοποιείται για την ενθυλάκωση της πληροφορίας που συνοδεύει ένα

νήµα. Ένα νέο νήµα εκκινεί µε τη δηµιουργία ενός νέου στιγµιότυπου της κλά-

σης, µπορεί δε να καλέσει οποιαδήποτε µέθοδο αντικείµενου του ιδίου προ-

γράµµατος στο οποίο βέβαια έχει πρόσβαση.

Στην ενότητα αυτή θα µάθετε να δηµιουργείτε ένα νήµα, να το εκκινείτε και

να το τερµατίζετε. Θα αναπτύξετε το πρώτο πολυ–νηµατικό πρόγραµµα σας

το οποίο, αν και µικρό, θα σας βοηθήσει στην κατανόηση των βασικών εννοι-

ών του ταυτόχρονου προγραµµατισµού. Για παραπέρα εξοικείωση µε τις

έννοιες της ενότητας, θα έχετε την ευκαιρία να εργασθείτε σε ένα πιο ολο-

κληρωµένο παράδειγµα που δίνεται στην ενότητα 9.3.

Page 168: Γλώσσες Προγραμματισμού II

1 6 8 ∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™

Για µία ακόµη φορά θα επισηµάνουµε πως ο ταυτόχρονος προγραµµατισµός

αποτελεί µια από τις πλέον σύνθετες µορφές προγραµµατισµού. Οποιαδήπο-

τε δυσκολία µην σας απογοητεύσει. Θέλει πολύ επιµονή και υποµονή.

9.2.1 ∏ ÎÏ¿ÛË Thread

H κλάση Thread έχει διάφορους δηµιουργούς. ∆ιακρίνουµε τους

public Thread(String threadName)

public Thread()

Ο πρώτος δηµιουργεί ένα Thread µε όνοµα που προσδιορίζει το όρισµα

threadName, ενώ ο δεύτερος δίνει σαν όνοµα τη συνένωση του αλφαριθµη-

τικού "Thread–" µ’ ένα ακέραιο, π.χ. Thread–1, Thread–2, κ.λ.π.

Η πρόταση

Thread ping = new Thread(new String("ping"));

δηµιουργεί ένα στιγµιότυπο της Thread µε όνοµα «ping». Κάθε στιγµιότυ-

πο της Thread ή υποκλάσης της, µετά τη δηµιουργία του, µπορεί να διαµορ-

φωθεί (configured) και στη συνέχεια να εκτελεστεί. Η διαµόρφωσή του περι-

λαµβάνει την απόδοση ονόµατος, προτεραιότητας και των λοιπών παραµέ-

τρων του. Όταν το στιγµιότυπο Thread είναι έτοιµο για εκτέλεση, καλούµε

τη µέθοδο start. Η start γεννά ένα καινούργιο νήµα εκτέλεσης σύµφωνα µε

τα δεδοµένα του στιγµιότυπου, καλεί τη µέθοδο run και επιστρέφει τον έλεγ-

χο στο σηµείο κλήσης. Το νέο νήµα εκτελείται ταυτόχρονα µε τον κώδικα που

το δηµιούργησε. H start εγείρει µια IllegalThreadStateException

εξαίρεση, αν το νήµα στο οποίο απευθύνεται έχει ήδη εκκινήσει.

Στη µέθοδο run τοποθετούµε τον κώδικα που θέλουµε να εκτελεί το συγκε-

κριµένο νήµα εκτέλεσης. Ο κώδικας του σχήµατος 9.1 ορίζει την κλάση

PingPong να κληρονοµεί την Thread και να προσδιορίζει ένα νήµα που θα

εµφανίζει στην οθόνη την λέξη word µε ταυτόχρονη εµφάνιση του αριθµού

των εµφανίσεων της από την εκκίνηση του νήµατος. Η delay προσδιορίζει

το χρόνο που θέλουµε το νήµα να είναι σε ανάπαυση. Ένα νήµα µπαίνει σε

ανάπαυση καλώντας τη static µέθοδο sleep µε όρισµα το χρόνο ανάπαυσης

σε χιλιοστά του δευτερολέπτου. Κατά τη διάρκεια ανάπαυσης το νήµα δεν

ανταγωνίζεται για τον επεξεργαστή δίνοντας έτσι δυνατότητα στα άλλα

νήµατα χαµηλότερης προτεραιότητας να εκτελεστούν.

Μεταξύ των άλλων µεθόδων της κλάσης Thread διακρίνουµε τις ακόλουθες:

Page 169: Γλώσσες Προγραμματισμού II

• Η µέθοδος interrupt, η οποία έχει σαν αποτέλεσµα τη διακοπή ενός νήµα-

τος εκτέλεσης.

• Η interrupted µέθοδος επιστρέφει true, αν το νήµα είναι σε διακοπή

αλλιώς επιστρέφει false.

class PingPong extends Thread

String word; // ϤÍË ÁÈ· ÂÎÙ‡ˆÛË

int delay; // ¯ÚfiÓÔ˜ ·Ó¿·˘Û˘

PingPong(String wordToPrint, int pauseTime)

word = wordToPrint;

delay = pauseTime;

public void run()

try

for(int i=0;;i++)

System.out.print(word +"–" + i + " ");

sleep(delay);

catch (InterruptedException e)

return; // ÙÂÚÌ·ÙÈÛÌfi˜ ÙÔ˘ thread

• H µέθοδος suspend αναστέλλει την λειτουργία ενός νήµατος εκτέλεσης,

ενώ η resume ξαναρχίζει την εκτέλεση του νήµατος. ∆εν έχει επίδραση

σε ένα νήµα το οποίο εκτελείται.

• Η µέθοδος stop τερµατίζει την εκτέλεση ενός νήµατος.

• Η µέθοδος isAlive επιστρέφει true, εάν έχει κληθεί η start για ένα συγκεκρι-

µένο νήµα και το νήµα δεν έχει τερµατιστεί. Ο τερµατισµός ενός νήµατος

γίνεται είτε µε τη µέθοδο stop είτε γιατί η run ολοκλήρωσε την εκτέλεση της.

1 6 9Y ¶ √ ™ ∆ ∏ ƒ π • ∏ ∆∞ À ∆ √ à ƒ √ ¡ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À ∞ ¶ √ ∆ ∏ ¡ J AVA

™¯‹Ì· 9.1

Κλάση PingPong

Page 170: Γλώσσες Προγραμματισμού II

1 7 0 ∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™

• Οι µέθοδοι setName, getName και setPriority, getPriority, παρέχουν

πρόσβαση στο όνοµα και στην προτεραιότητα του νήµατος αντίστοιχα.

• Τέλος, η static µέθοδος currentThread επιστρέφει µια αναφορά στο τρέ-

χον νήµα.

Αναπτύξτε ένα πρόγραµµα που θα δηµιουργεί δύο νήµατα εκτέλεσης τα

οποία να τυπώνουν τις λέξεις "PING" και "pong" και να έχουν χρόνους

ανάπαυσης 30 και 60 χιλιοστά του δευτερολέπτου αντίστοιχα.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

9.1

9.2.2 ∫‡ÎÏÔ˜ ˙ˆ‹˜ ÂÓfi˜ Ó‹Ì·ÙÔ˜

Από τα παραπάνω διαφαίνεται, πως ένα νήµα, κατά τη διάρκεια της ζωής του

(life cycle) µπορεί να βρίσκεται σε διάφορες καταστάσεις, όπως φαίνεται στο

σχήµα 9.2. Ένα νήµα που µόλις δηµιουργήθηκε, είναι στην κατάσταση born.

Το νήµα παραµένει στην κατάσταση αυτή µέχρι να του αποσταλεί το µήνυ-

µα start, οπότε και µπαίνει στην κατάσταση runnable.

runnable

suspended waitingsleeping

bornstart

Stop complete

Aίτηση I/

O

wai

t

suspend

sleep

resu

me

yie

ld

disp

atch

notify

notify All

Oλοκλήρωση I/O

Tέλος χ

ρόνου ανάπαυσης

blocked

deadrunning

™¯‹Ì· 9.2

Κύκλος ζωής (life cycle)

νήµατος.

Όταν ένα νήµα είναι στην κατάσταση runnable, λέµε πως είναι προγραµµατι-

σµένο (scheduled), που σηµαίνει πως είναι σε µια ουρά (queue) περιµένοντας

τη σειρά του να εκτελεστεί. Ανταγωνίζεται δηλαδή µε άλλα νήµατα για να

καταλάβει τον επεξεργαστή. Νήµατα µε µεγαλύτερη προτεραιότητα έχουν

Page 171: Γλώσσες Προγραμματισμού II

καλύτερη θέση στην ουρά, ενώ όταν πολλά νήµατα έχουν την ίδια προτεραι-

ότητα, ταξινοµούνται µε βάση τη σειρά εισόδου στην ουρά. Όταν το τρέχον

νήµα εκχωρήσει τον έλεγχο (relinquishes control), εκτελείται το πρώτο νήµα

της ουράς. Το νήµα αυτό λέµε ότι µπήκε στην κατάσταση running. Όταν ένα

νήµα είναι στην κατάσταση running, σηµαίνει πως κατέχει τον πολύτιµο πόρο

του επεξεργαστή. Ο κώδικάς του εκτελείται µέχρι ένα µεγαλύτερης προτεραι-

ότητας νήµα να πάρει τη θέση του ή το ίδιο να ελευθερώσει τον επεξεργαστή.

Ένα νήµα ελευθερώνει τον επεξεργαστή µ’ έναν από τους παρακάτω τρόπους:

1. Αποδίδει τον έλεγχο (yield), γεγονός που σηµαίνει ότι µπαίνει στη σειρά

προγραµµατισµένων νηµάτων, δηλαδή µεταβαίνει στην κατάσταση

runnable.

2. Μεταβαίνει σε κατάσταση ανάπαυσης (sleep) για συγκεκριµένο χρονικό

διάστηµα, γεγονός που σηµαίνει πως δε θα εισαχθεί στην ουρά για εκτέ-

λεση παρά µόνο µετά την παρέλευση του καθορισµένου χρόνου.

3. Μεταβαίνει στην κατάσταση wait, που σηµαίνει πως είναι σ’ αναµονή

ενός συµβάντος, για να τοποθετηθεί εκ νέου στην ουρά. To συµβάν γνω-

στοποιείται µε την κλήση της µεθόδου notify ή notifyAll από ένα άλλο

νήµα, που έχει κάποια σχέση µε το εν λόγω νήµα.

4. Μεταβαίνει σε κατάσταση blocked σε ειδικές περιπτώσεις, όπως αυτή της

αίτησης µιας λειτουργίας εισόδου–εξόδου. Στην περίπτωση αυτή το νήµα

επανέρχεται στη runnable, όταν η είσοδος–έξοδος που ζητήθηκε γίνει δια-

θέσιµη.

5. Μεταβαίνει σε κατάσταση αναστολής (suspend), απ’ όπου θα µεταβεί στη

runnable, µόνο όταν δεχτεί το µήνυµα resume από άλλο νήµα.

Τέλος, ένα νήµα τερµατίζει τη διάρκεια ζωής του, όταν δεχτεί το µήνυµα stop

ή ολοκληρώσει την αποστολή του.

Όταν έρθει στην ουρά ένα νήµα µε µεγαλύτερη προτεραιότητα από το νήµα

που εκτελείται τότε αναστέλλεται η εκτέλεση του τρέχοντος για να εκτελε-

στεί το νήµα µε τη µεγαλύτερη προτεραιότητα. Μόλις αυτό ολοκληρώσει τη

δράση του, µεταβαίνει στην κατάσταση sleeping. Επειδή το σύστηµα δε δια-

κόπτει την εκτέλεση ενός νήµατος για να εκτελέσει ένα άλλο της ίδιας προ-

τεραιότητας, θα πρέπει να φροντίζουµε τα νήµατα αυτά να αποδίδουν περιο-

δικά τον έλεγχο (yield control), ώστε να δίνουν την ευκαιρία σε άλλα νήµα-

τα ίδιας προτεραιότητας να εκτελεστούν.

1 7 1Y ¶ √ ™ ∆ ∏ ƒ π • ∏ ∆∞ À ∆ √ à ƒ √ ¡ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À ∞ ¶ √ ∆ ∏ ¡ J AVA

Page 172: Γλώσσες Προγραμματισμού II

1 7 2 ∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™

9.2.3 ™˘Á¯ÚÔÓÈÛÌfi˜ ÓËÌ¿ÙˆÓ

Καθώς τα νήµατα της Java τρέχουν στον ίδιο χώρο µνήµης, µπορούν να έχουν

πρόσβαση σε µεθόδους και µεταβλητές κοινών αντικειµένων. Στην πράξη

υπάρχουν πολλοί λόγοι, ώστε δύο ή περισσότερα νήµατα να πρέπει να έχουν

πρόσβαση σε κοινά δεδοµένα και πόρους. Στις περιπτώσεις αυτές είναι απα-

ραίτητη η παροχή διευκολύνσεων συγχρονισµού από τη γλώσσα προγραµ-

µατισµού. Φαντασθείτε το πρόβληµα που θα δηµιουργούσε µια ταυτόχρονη

προσπάθεια πολλών νηµάτων να γράψουν στο ίδιο αρχείο ή στον ίδιο εκτυ-

πωτή ή ακόµη να διαβάσουν από την ίδια συσκευή εισόδου. Ή ακόµη αυτό

που δηµιουργείται, όταν ένα νήµα αποθηκεύει τιµές στις µεταβλητές ενός

κοινά χρησιµοποιούµενου αντικειµένου και ταυτόχρονα ένα άλλο προσπα-

θήσει να τις διαβάσει πριν το πρώτο ολοκληρώσει την αποθήκευση.

Η βασική αρχή πάνω στην οποία στηρίζεται ο συγχρονισµός των νηµάτων

βασίζεται στην απαγόρευση δύο ή περισσότερων νηµάτων να έχουν ταυτό-

χρονη πρόσβαση στον ίδιο πόρο. Σαν πόρος µπορεί να θεωρηθεί όχι µόνο

κάποια περιφερειακή συσκευή αλλά και κάθε αντικείµενο του περιβάλλο-

ντος προγραµµατισµού. Ειδικά η Java απαγορεύει σε δύο ή περισσότερα

νήµατα να εκτελέσουν ταυτόχρονα πάνω σ’ ένα αντικείµενο ενέργειες που

συγκρούονται. Και καθώς το περιβάλλον δεν µπορεί να γνωρίζει για κάθε

πόρο ποιες ενέργειες συγκρούονται, είναι ευθύνη του προγραµµατιστή να το

γνωστοποιήσει χρησιµοποιώντας κατάλληλα τη λέξη κλειδί synchronized.

O προγραµµατιστής όταν αναπτύσσει µια κλάση η οποία θέλει να µπορεί να

χρησιµοποιηθεί σε εφαρµογή πολλαπλών νηµάτων πρέπει να αποφασίσει

ποιες µέθοδοι δεν µπορούν να εκτελούνται ταυτόχρονα από δύο ή περισσό-

τερα νήµατα. Τις µεθόδους αυτές που µπορεί να είναι µέθοδοι στιγµιότυπου

¶ÚÔÙÂÚ·ÈfiÙËÙ˜ ÓËÌ¿ÙˆÓ

Κάθε νήµα έχει ένα βαθµό προτεραιότητας που είναι µεταξύ Thread.

MIN_PRIORITY (µια σταθερή ίση µε 1) και Thread.MΑΧ_PRIORITY

(µια σταθερή ίση µε 10). Αν δεν ορισθεί από τον προγραµµατιστή, ο βαθ-

µός προτεραιότητας είναι ίδιος µε την του νήµατος δηµιουργού. Σε περί-

πτωση που δεν υπάρχει νήµα δηµιουργός η προτεραιότητα τίθεται στον

από σύµβαση βαθµό προτεραιότητας Thread.NORM_PRIORITY (µια στα-

θερή ίση µε 5).

Page 173: Γλώσσες Προγραμματισμού II

ή κλάσης ορίζει σαν synchronized. Μια κλάση µπορεί να έχει απροσδιό-

ριστο αριθµό synchronized µεθόδων.

Γενικότερα ο προγραµµατιστής µπορεί να προσδιορίζει τµήµατα κώδικα που

δεν πρέπει να εκτελούνται ταυτόχρονα. Τα τµήµατα αυτά είναι γνωστά σαν

κρίσιµα τµήµατα (critical sections). Στην πιο γενική του µορφή το keyword

synchronized χρησιµοποιείται για τη δηµιουργία της πρότασης synchronized

µε τη µορφή:

synchronized (έκφραση) πρόταση,

όπου έκφραση είναι µια έκφραση που πρέπει να προσδιορίζει ένα αντικείµε-

νο και πρόταση είναι ο κώδικας του κρίσιµου τµήµατος, συνήθως ένα µπλοκ

προτάσεων που περικλείονται σε .

Για να εκτελέσει ένα νήµα µια synchronized πρόταση σ’ ένα αντικείµε-

νο, θα πρέπει πρώτα να αποκτήσει το µοναδικό κλειδί (exclusive lock) που

έχει αποδοθεί από το περιβάλλον στο συγκεκριµένο αντικείµενο. Αν το κλει-

δί είναι διαθέσιµο, το δεσµεύει και αρχίζει την εκτέλεση του κρίσιµου κώδι-

κα. Αποδεσµεύει δε το κλειδί µόνο µετά το τέλος της εκτέλεσης του κρίσι-

µου κώδικα. Στο διάστηµα αυτό κανένα άλλο νήµα δεν µπορεί να αποκτή-

σει το κλειδί. Αν το κλειδί δεν είναι διαθέσιµο, γιατί είναι κατειληµµένο από

άλλο νήµα, τότε το νήµα µπαίνει σε µια κατάσταση αναµονής έως ότου απο-

δεσµευτεί το µοναδικό κλειδί, οπότε και διεκδικεί την απόκτησή του.

H Java, για να υποστηρίξει το συγχρονισµό νηµάτων χρησιµοποιεί την τεχνι-

κή των ελεγκτών (monitors) που εισήγαγε ο C.A.R. Hoare [Hoare 74], απο-

δίδοντας έναν ελεγκτή σε κάθε αντικείµενο που έχει µία τουλάχιστο

synchronized πρόταση. Ο ελεγκτής επιτρέπει µόνο σ’ ένα νήµα κάθε χρο-

νική στιγµή, να εκτελεί µια synchronized µέθοδο. Αν στο αντικείµενο

υπάρχουν περισσότερες synchronized µέθοδοι, µόνο µία µπορεί να είναι

ενεργή ανά πάσα χρονική στιγµή. Όλα δε τα άλλα νήµατα που θέλουν να

εκτελέσουν synchronized µεθόδους θα πρέπει να περιµένουν.

Για εκτέλεση synchronized µεθόδου κλάσης πρέπει να αποκτηθεί το κλει-

δί της κλάσης, ενώ για εκτέλεση µεθόδου στιγµιότυπου πρέπει να αποκτη-

θεί το κλειδί του στιγµιότυπου, στο οποίο αναφέρεται η µέθοδος.

9.2.4 √È Ì¤ıÔ‰ÔÈ wait Î·È notify

Όταν ολοκληρωθεί η εκτέλεση µιας synchronized µεθόδου, το αντικείµενο

είναι πλέον διαθέσιµο και ο ελεγκτής επιτρέπει στο υψηλότερης προτεραιό-

1 7 3Y ¶ √ ™ ∆ ∏ ƒ π • ∏ ∆∞ À ∆ √ à ƒ √ ¡ √ À ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À ∞ ¶ √ ∆ ∏ ¡ J AVA

Page 174: Γλώσσες Προγραμματισμού II

1 7 4 ∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™

τητας σε αναµονή, νήµα να προχωρήσει στην εκτέλεση της synchronized

µεθόδου, για την οποία ήταν σε αναµονή.

Ένα νήµα που εκτελεί µια synchronized µέθοδο, µπορεί να διαπιστώσει,

πως δεν µπορεί να προχωρήσει και οικειοθελώς καλεί την wait, µε συνέπεια

να αποσυρθεί το νήµα από τον ανταγωνισµό για τον επεξεργαστή αλλά και

τον ελεγκτή. Το νήµα µπαίνει σε µια ουρά σε αναµονή του µηνύµατος notify

από ένα άλλο νήµα το οποίο µόλις ολοκλήρωσε την εκτέλεση µιας

synchronized µεθόδου. Εάν ένα νήµα καλέσει την notifyAll, όλα τα νήµα-

τα που είναι σε αναµονή επανέρχονται στην προσπάθεια απόκτησης του

δικαιώµατος πρόσβασης στο αντικείµενο.

™‡ÓÔ„Ë ÂÓfiÙËÙ·˜

Στην ενότητα αυτή αναφέραµε τις κατασκευές µε τις οποίες η Java µας επι-

τρέπει να αναπτύξουµε προγράµµατα που θα αποτελούνται από περισσότερα

του ενός νήµατα. Είδαµε πως η κλάση Thread απλοποιεί σε µεγάλο βαθµό τη

διαδικασία δηµιουργίας, ελέγχου και καταστροφής νηµάτων, προσφέροντας

ένα υψηλότερο επίπεδο αφαιρετικότητας απ’ ό,τι οι βασικές έννοιες του ταυ-

τόχρονου προγραµµατισµού.

Ιδιαίτερη προσοχή χρειάζεται στις περιπτώσεις όπου δύο ή περισσότερα νήµα-

τα απαιτούν ταυτόχρονη πρόσβαση στον ίδιο πόρο. Είναι αποκλειστική ευθύ-

νη του προγραµµατιστή να προσδιορίσει για κάθε πόρο, τις ενέργειες που δεν

µπορούν να εκτελούνται ταυτόχρονα από δύο ή περισσότερα νήµατα.

9.3 §‡ÛË ÛÙÔ Úfi‚ÏËÌ· ·Ú·ÁˆÁÔ‡–ηٷӷψً

∂ÈÛ·ÁˆÁÈΤ˜ ¶·Ú·ÙËÚ‹ÛÂȘ

Το πρόβληµα παραγωγού–καταναλωτή είναι µια αφαιρετική µορφή των εφαρ-

µογών του ταυτόχρονου προγραµµατισµού. Ο παραγωγός θα παράγει, εάν

και µόνο εάν ο καταναλωτής είναι έτοιµος να καταναλώσει. Απαιτείται λοι-

πόν η πραγµατοποίηση µιας συνάντησης (ενός ραντεβού) µεταξύ των δυο

διεργασιών, του παραγωγού και του καταναλωτή. Αν µια από τις δύο διερ-

γασίες φθάσει πρώτη στο ραντεβού θα πρέπει να περιµένει την άλλη. Το

ραντεβού, αν και είναι λογική αντιµετώπιση δηµιουργεί προβλήµατα, αν οι

ρυθµοί παραγωγής και κατανάλωσης διαφοροποιούνται. Μια αποδοτικότε-

ρη λύση δίνεται χρησιµοποιώντας προσωρινή αποθήκευση. Η χρήση του

buffer για αποθήκευση των δεδοµένων πληκτρολόγησης είναι ένα παράδειγ-

Page 175: Γλώσσες Προγραμματισμού II

µα χρήσης της τεχνικής αυτής. Έτσι, επιτρέπεται στον χρήστη να παράγει πολ-

λές διαταγές χωρίς να περιµένει τον υπολογιστή να αντιµετωπίσει, «κατανα-

λώσει» κάθε διαταγή. Αν η περιοχή προσωρινής αποθήκευσης είναι αρκετά

µεγάλη για να αντιµετωπίζει αιχµές στην παραγωγή δεν παρατηρούνται

δυσλειτουργίες στο σύστηµα. Η λειτουργία µιας περιοχής προσωρινής απο-

θήκευσης µοιάζει µε τη λειτουργία της ανάρτησης ενός αυτοκινήτου, η οποία

δέχεται µια αιχµή ενέργειας και µετά την απελευθερώνει σιγά–σιγά ώστε το

αυτοκίνητο και οι επιβάτες να αντέξουν αυτή την είσοδο ενέργειας. Για µια

αναλυτική και σε βάθος θεώρηση του προβλήµατος παραγωγού–καταναλω-

τή µπορείτε να ανατρέξετε στην ενότητα 4.3 του [Ben 97].

Εµείς εδώ θα θεωρήσουµε την περίπτωση του προβλήµατος όπου η περιοχή

προσωρινής αποθήκευσης «χωράει» ένα αγαθό. Θα αναπτύξουµε ένα πρό-

γραµµα αποτελούµενο από δύο νήµατα ένα του παραγωγού (producer) και

ένα του καταναλωτή (consumer). Σε πρώτη φάση δε θα συγχρονίσουµε τις

δύο διεργασίες για να γίνει εµφανές το πρόβληµα που παρουσιάζεται. Στη

δεύτερη θα προσπαθήσουµε να αντιµετωπίσουµε το πρόβληµα εισάγοντας

συγχρονισµό µεταξύ των δύο διεργασιών.

9.3.1 ∞ÓÙÈÌÂÙÒÈÛË ¯ˆÚ›˜ Û˘Á¯ÚÔÓÈÛÌfi

Πριν προχωρήσουµε στον ορισµό των κλάσεων παραγωγού και καταναλω-

τή θα πρέπει να αναπαραστήσουµε τον αποθηκευτικό χώρο. Υποθέτοντας

πως αυτός έχει χωρητικότητα ενός αγαθού και διαθέτει δύο µεθόδους, µια

για αποθήκευση του αγαθού και µια για ανάκληση, εκτελέστε την άσκηση

αυτοαξιολόγησης 2/κεφ.9.

Για τον ορισµό των κλάσεων παραγωγού και καταναλωτή, θα πρέπει να

λάβουµε υπόψη ότι ο παραγωγός µας πρέπει να παράγει και ο καταναλωτής

µας να καταναλώνει ένα αγαθό τύπου int σε τυχαία χρονικά διαστήµατα. Για

να πετύχουµε κάτι τέτοιο αρκεί να βάζουµε το νήµα, που αναπαριστά την

κάθε διεργασία, σε ανάπαυση µε τη µέθοδο sleep, φροντίζοντας να της περ-

νάµε σαν όρισµα έναν τυχαίο αριθµό. Η πρόταση

Thread.sleep((int)(Math.random() * 3000));

βάζει το νήµα που θα την εκτελέσει σε ανάπαυση για τυχαίο χρονικό διά-

στηµα που είναι µεταξύ 0 και 3 δευτερόλεπτα.

1 7 5§ À ™ ∏ ™ ∆ √ ¶ ƒ √ µ § ∏ ª ∞ ¶ ∞ ƒ∞ ° ø ° √ À – ∫ ∞∆∞ ¡ ∞ § ø ∆ ∏

Page 176: Γλώσσες Προγραμματισμού II

∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™1 7 6

Θεωρώντας το αγαθό τύπου int, δώστε τον ορισµό της κλάσης που αναπα-

ριστά τον αποθηκευτικό χώρο.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

9.2

∆ώστε τον ορισµό της κλάσης ενός παραγωγού που παράγει δώδεκα αγαθά

τύπου int σε τυχαία χρονικά διαστήµατα που απέχουν µεταξύ τους από 0

µέχρι 3 δευτερόλεπτα. Κάντε το ίδιο για την κλάση του καταναλωτή. Χρη-

σιµοποιήστε για τον ορισµό τους την αναπαράσταση του αποθηκευτικού

χώρου όπως αυτή δόθηκε στην άσκηση αυτοαξιολόγησης 2/κεφ.9.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘

9.3

Αναπτύξτε µια εφαρµογή σε Java που θα δηµιουργεί έναν παραγωγό και

έναν καταναλωτή, όπως ορίστηκαν από την Άσκηση Aυτοαξιολόγησης 3.

¢Ú·ÛÙËÚÈfiÙËÙ·9.1

Σχολιάστε το αποτέλεσµα της εκτέλεσης του προγράµµατος.¢Ú·ÛÙËÚÈfiÙËÙ·9.2

9.3.2 AÓÙÈÌÂÙÒÈÛË ÌÂ Û˘Á¯ÚÔÓÈÛÌfi

Για να διασφαλίσουµε ότι ο καταναλωτής καταναλώνει µόνο µετά από την

παραγωγή αγαθού από τον παραγωγό και ότι ο παραγωγός παράγει µόνο

αφού δεν υπάρχει ήδη αγαθό για κατανάλωση, πρέπει να εισάγουµε συγ-

χρονισµό µεταξύ των δύο διεργασιών.

Ορίζουµε τις µεθόδους put και get της κλάσης Buffer σαν synchronized

και τροποποιούµε το σώµα τους ώστε η κάθε µέθοδος να µπαίνει στο κρίσι-

µο τοµέα της, αφού διασφαλίσει αποκλειστική πρόσβαση στο αντικείµενο.

Για το λόγο αυτό ορίζουµε τη boolean µεταβλητή empty, την οποία θα χρη-

σιµοποιούν οι δύο µέθοδοι για να προσδιορίσουν αν µπορούν να θέσουν ή να

πάρουν αγαθό από την κοινή αποθήκη. Η µεταβλητή αυτή είναι γνωστή σαν

µεταβλητή συνθήκης του ελεγκτή (monitor’s condition variable). Χρησιµο-

ποιώντας την empty η περιγραφή της put διαµορφώνεται όπως παρακάτω

όσο η αποθήκη είναι γεµάτη

περίµενε

Page 177: Γλώσσες Προγραμματισμού II

βάλε το νέο αγαθό στην αποθήκη

ενηµέρωσε την condition variable ότι η αποθήκη είναι γεµάτη

ενηµέρωσε τα νήµατα που είναι σε αναµονή χρήσης του αντικειµένου ότι αυτό

είναι πλέον διαθέσιµο

1 7 7™ Y N O æ H

∆ώστε την περιγραφή σε δοµηµένα Ελληνικά της synchronized µεθό-

δου get της κλάσης Buffer.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘9.4

∆ώστε τον ορισµό της κλάσης Buffer, όπως διαµορφώνεται µε τις

synchronized µεθόδους put και get.

ÕÛÎËÛË ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘9.5

Μετατρέψτε τον κώδικα του προγράµµατος της ∆ραστηριότητας 1 εισά-

γοντας συγχρονισµό µεταξύ παραγωγού και καταναλωτή. Εκτελέστε το και

σχολιάστε το αποτέλεσµα.

¢Ú·ÛÙËÚÈfiÙËÙ·9.3

Μια καλύτερη υλοποίηση επιτυγχάνεται χρησιµοποιώντας µεγαλύτερο απο-

θηκευτικό χώρο. Αυτό επιτρέπει στον παραγωγό και καταναλωτή να παρά-

γουν και καταναλώνουν αντίστοιχα µε διαφορετικές ταχύτητες καθώς ο απο-

θηκευτικός χώρος µπορεί να απορροφήσει πλέον τα αγαθά που προκύπτουν

σε µια περίοδο υψηλής παραγωγικότητας του παραγωγού. Για µια αναλυτι-

κή περιγραφή αυτής της µορφής υλοποίησης µπορείτε να ανατρέξετε στην

ενότητα 13.8 του [Deitel 98] όπου δίνεται και µια ενδεικτική υλοποίηση µε

τη µορφή ενός applet.

™‡ÓÔ„Ë

Στο κεφάλαιο αυτό αναφερθήκαµε στις πολύ βασικές έννοιες του ταυτόχρο-

νου προγραµµατισµού µε µοναδικό στόχο να εισάγουµε τις κατασκευές εκεί-

νες της Java, µε τις οποίες η γλώσσα υποστηρίζει τη συγγραφή πολυ–νηµα-

τικών εφαρµογών. Ο ταυτόχρονος προγραµµατισµός είναι από τις πιο δύσκο-

λες µορφές προγραµµατισµού µε σύνθετους αλγόριθµους και αντίστοιχα πολύ-

πλοκες κατασκευές υλοποίησης.

Page 178: Γλώσσες Προγραμματισμού II

1 7 8 ∫ ∂ º ∞ § ∞ π √ 9 : T∞ À ∆ √ à ƒ √ ¡ √ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ ™

Η Java υποστηρίζει τον ταυτόχρονο προγραµµατισµό επιτρέποντας την ανα-

παράσταση ενός νήµατος από µια κλάση που πρέπει να είναι απόγονος της

κλάσης Thread της βασικής βιβλιοθήκης της. Προσφέρει επίσης το interface

Runnable για την περίπτωση που το νήµα µας αναπαρίσταται από κλάση που

είναι απόγονος άλλης κλάσης εκτός της Thread και, καθώς η Java δεν υπο-

στηρίζει πολλαπλή κληρονοµικότητα, µπορούµε να δηλώσουµε την κλάση µας

να υλοποιεί το Runnable interface.

Κάθε νήµα µπορεί να είναι σε µια κατάσταση από ένα σύνολο διακριτών και

σαφώς ορισµένων καταστάσεων, όπου οι µέθοδοι wait και notify έχουν σηµα-

ντική σηµασία για την υποστήριξη του συγχρονισµού µεταξύ διεργασιών.

Τέλος, η πρόταση syncronized χρησιµοποιείται για την προστασία των κρί-

σιµων τοµέων ενός αντικείµενου.

BÈ‚ÏÈÔÁÚ·Ê›·

[1] [Ben 98]

M.Ben–Ari «Ταυτόχρονος Προγραµµατισµός» Prentice Hall International,

1998. Ελληνική µετάφραση από τον Κλειδάριθµο.

[2] [Hoare 74]

C.A.R. Hoare «Monitors:An operating System Structuring concept»

Communications of the ACM, vol.17, No.10, Oct. 1974 pp 549–557.

[3] [Deitel 98]

Deitel & Deitel «Java: How to program», Second edition, Prentice Hall

International 1998.

[4] [Dijkstra 68]

Dijkstra, E.W.: «Co–operating sequential processes» In F.Genuys (Ed.),

Programming Languages: NATO Advanced Stydy Institute. Academic

Press 1968, London, 43–112.

[5] [Sethi 97]

Ravi Sethi, «Programming Languages: Concepts and Constructs» 2nd

Edition, Addison Wesley 1996. Reprinted with corrections April 1997.

Page 179: Γλώσσες Προγραμματισμού II

A·ÓÙ‹ÛÂȘ AÛ΋ÛÂˆÓ A˘ÙÔ·ÍÈÔÏfiÁËÛ˘

1.1

Ο ιδιοκτήτης, ο πελάτης και ο υπάλληλος αποτελούν εξειδικεύσεις της πιο

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

παρακάτω διάγραµµα κλάσεων[1]:

[1] το διάγραµµα κλάσεων αναπαριστά κλάσεις και τις µεταξύ αυτών συσχετίσεις

(class associations).

Πρόσωπο

YπάλληλοςIδιοκτήτης Πελάτης

Hλεκτρική συσκευή

Tοστιέρα Φούρνος µικροκυµάτων

Tοστιέρα Φούρνος µικροκυµάτων

YπάλληλοςIδιοκτήτης

Fast food

Η τοστιέρα και ο φούρνος µικροκυµάτων αποτελούν εξειδικεύσεις της έννοι-

ας ηλεκτρική συσκευή.

Τέλος, οι κλάσεις ιδιοκτήτης, υπάλληλος, τοστιέρα και φούρνος µικροκυµάτων,

σχετίζονται µε την κλάση fast food µε σχέση «µέρους–όλου» (συνάθροισης).

Page 180: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I1 8 0

Αν η απάντηση σας είναι διαφορετική ως προς την αναπαράσταση των κλά-

σεων και των µεταξύ των σχέσεων, δεν πειράζει. Εντοπίσατε την ουσία, που

είναι η αναγνώριση των σχέσεων. Είµαι βέβαιος, πως την επόµενη φορά θα

θυµηθείτε το σωστό συµβολισµό.

Αν δεν αναγνωρίσατε σωστά τις σχέσεις, σηµαίνει πως δεν δίνετε την απα-

ραίτητη προσοχή στις δραστηριότητες. Για το λόγο αυτό, διαβάστε πάλι προ-

σεκτικά τα περί σχέσεων µεταξύ των κλάσεων. Αποτελεί πολύ σηµαντικό

θέµα για την ΑΠ. Στη συνέχεια εκτελέστε πάλι τη ∆ραστηριότητα 1.2.

Αν απαντήσατε σωστά συγχαρητήρια, τα πάτε θαυµάσια µε την ΑΠ.

2.1

import λέξη κλειδί extends

applet κλάση συστήµατος Applet

awt κλάση προγραµµατιστή paint

public πακέτο Graphics

class στιγµιότυπο g

HelloWorld µέθοδος drawstring

Αν δεν καταφέρατε να βρείτε όλες τις σωστές αντιστοιχίσεις, µην απογοη-

τεύεστε. Είναι νέες έννοιες. Σας συνιστώ όµως να διαβάσετε πιο προσεκτι-

κά αυτή τη φορά την υποενότητα 2.2.3. Θα σας βοηθήσει πολύ στην µελέτη

του επόµενου κεφαλαίου.

Αν όλες οι αντιστοιχίσεις σας είναι σωστές, συγχαρητήρια. Είστε έτοιµοι για

το επόµενο κεφάλαιο.

3.1

Η κλάση κύκλος περιέχει τα ίδια δεδοµένα που περιέχει και η δοµή κύκλος,

αλλά επιπλέον περιέχει και τις µεθόδους οι οποίες προσδίδουν συµπεριφο-

ρά στα στιγµιότυπά της.

3.2

Η δήλωση Rectangle(int x1, int y1, int x2, int y2) δεν είναι σωστή σε συν-

δυασµό βέβαια µε τον προϋπάρχοντα δηµιουργό Rectangle(int x, int y, int w,

int h).

Page 181: Γλώσσες Προγραμματισμού II

Εκ πρώτης όψεως και θεωρώντας τον µηχανισµό της υπερφόρτωσης θα µπο-

ρούσαµε να πούµε «Ναι! είναι σωστή». Προσέξτε όµως: οι δύο δηµιουργοί

έχοντας ίδιο όνοµα, αριθµό και τύπο ορισµάτων και επιστρεφόµενης τιµής, δεν

είναι δυνατό να διακριθούν από το σύστηµα και εποµένως µια τέτοια επιλογή

είναι λανθασµένη. Υπερβολική υπερφόρτωση, θα µπορούσαµε να πούµε.

Αν δεν απαντήσατε σωστά, µην ανησυχείτε. Θα πρέπει όµως να είστε πιο

προσεκτικοί στη διαµόρφωση των απαντήσεων, καθώς είµαι σχεδόν σίγου-

ρος ότι είχατε την απαραίτητη γνώση. Αν όχι, θα πρέπει να µελετήσετε πάλι

τις Υποενότητες 3.3.3 και 3.3.4, που αναφέρονται σε πολλαπλούς δηµιουρ-

γούς και υπερφόρτωση αντίστοιχα.

Αν απαντήσατε σωστά, µπράβο σας. Είστε πολύ παρατηρητικοί.

1 8 1A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

3.3

Ο ζητούµενος πηγαίος κώδικας δίνεται στη συνέχεια:

// ¶ËÁ·›Ô˜ ÎÒ‰Èη˜ ¿ÛÎËÛ˘ ∞˘ÙÔ·ÍÈÔÏfiÁËÛ˘ 3

public class CircleTest∞3

public static void main(String[] args)

Circle a = new Circle(2.0,2.0,3.0);// ‰ËÌÈÔ˘ÚÁ›· ·ÎÏÔ˘ a Î·È ·fi‰ÔÛË

// ·Ú¯ÈÎÒÓ ÙÈÌÒÓ

Circle b = new Circle(5.0,2.0,2.0);// ‰ËÌÈÔ˘ÚÁ›· ·ÎÏÔ˘ b Î·È ·fi‰ÔÛË

// ·Ú¯ÈÎÒÓ ÙÈÌÒÓ

// ÂÎÙ‡ˆÛË ÛÙÔȯ›ˆÓ ·ÎÏÔ˘ a Î·È b fiˆ˜ ¿ÛÎËÛË 1

System.out.println("∞ÚÈıÌfi˜ ÛÙÈÁÌÈfiÙ˘ˆÓ:" + CCiirrccllee..ccoouunntt);

class Circle

ssttaattiicc iinntt ccoouunntt == 00;;

public static final double PI=3.1415926;

public double x,y,r;

public Circle(double x, double y, double r)

this.x=x; this.y=y; this.r=r; ccoouunntt++++;;

Page 182: Γλώσσες Προγραμματισμού II

1 8 2 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Πρέπει να επισηµάνουµε πως οι δηλώσεις σταθερών έχουν άµεση επίδραση

στη βελτίωση των επιδόσεων του προγράµµατος. Ο µεταγλωττιστής σε

εκφράσεις 2*PI*r προϋπολογίζει την τιµή 2*PI, αντί να την αφήνει για τον

διερµηνευτή.

Αξίζει να σηµειώσουµε πως ο κανόνας αναγνωσιµότητας της C, σύµφωνα

µε τον οποίο οι σταθερές γράφονται µε κεφαλαία, έχει υιοθετηθεί και από

την Java. Προσέξτε επίσης τον τρόπο µε τον οποίο αναφέρεται η main στην

count της Circle.

Αν ο κώδικάς σας µοιάζει µε τον παραπάνω, µπράβο σας. Κάνατε καλή δου-

λειά. Η προσπάθειά σας άρχισε να αποδίδει.

Αν όχι, µην απογοητεύεστε. Θα πρέπει όµως να µελετάτε πιο αποτελεσµα-

τικά. Μελετήστε πάλι το Παράδειγµα 1 και στη συνέχεια τη θεωρία του

Κεφαλαίου 3 τη σχετική µε τη δήλωση δηµιουργού (Ενότητα 3.3), καθώς

και τις µεταβλητές και σταθερές κλάσης (Υποενότητες 3.4.1 και 3.4.2). Θα

διαπιστώσετε πως έχετε τα απαραίτητα εφόδια για την συγγραφή του προ-

γράµµατος.

3.4

Η σωστή απάντηση είναι για µεν το δηµιουργό

public Point(Point p1,Point p2) x = p1.x + p2.x; y

= p1.x + p2.x;

για δε τον κώδικα, που δηµιουργεί το νέο σηµείο µε συντεταγµένες το άθροι-

σµα των συντεταγµένων των σηµείων p1 και p2,

Point p3 = Point(p1,p2);

µε την προϋπόθεση βέβαια, ότι προηγουµένως έχουν δηµιουργηθεί και έχουν

λάβει τις κατάλληλες τιµές τα στιγµιότυπα p1 και p2. Η εµφάνιση τέλος των

συντεταγµένων µπορεί να έχει µια µορφή σαν την παρακάτω:

System.out.println("p3.x:" + p3.x + "\tp3.y:" + p3.y);

Είναι ενδιαφέρον να παρατηρήσουµε την υπερφόρτωση της µεθόδου Point.

public double circumference( ) return 2*PI*r;

public double area( ) return PI*r*r;

Page 183: Γλώσσες Προγραμματισμού II

Οι δύο δηµιουργοί δέχονται αµφότεροι δύο ορίσµατα, αλλά διαφορετικού

τύπου σε κάθε δήλωση. Το γεγονός αυτό βοηθά το σύστηµα να προσδιορί-

σει την κατάλληλη σε κάθε περίπτωση συµπεριφορά.

Αν η απάντησή σας δεν συµφωνεί µε τις παραπάνω δύο πρώτες προτάσεις, θα

χρειαστεί να επιµείνετε ακόµη στο παρόν κεφάλαιο. ∆εν έχετε καταφέρει να

εξοικειωθείτε µε βασικές έννοιες που είναι πολύ απαραίτητες για τη συνέχεια.

Αν η απάντηση είναι όπως η παραπάνω, µε εξαίρεση την τρίτη πρόταση που

µπορεί να έχει διάφορες µορφές, µπράβο σας, συνεχίστε µε τον ίδιο ρυθµό.

3.5

Η σωστή αντιστοίχηση για την έκφραση System.out.println() είναι η παρακάτω

System πακέτο

κλάση

out µεταβλητή κλάση

µεταβλητή στιγµιότυπου

printIn µέθοδος κλάσης

µέθοδος στιγµιότυπου

Αν η απάντησή σας δεν είναι η παραπάνω, µην ανησυχείτε, είναι µια πολύ

δύσκολη άσκηση, αλλά µε πολύ ενδιαφέρον στην απάντηση της. Μελετήστε

την πολύ προσεκτικά. Θα χρειαστεί να ανατρέξετε στην τεκµηρίωση της

βασικής βιβλιοθήκης πάλι. Θα δείτε πως η System είναι µια κλάση που ορί-

ζει µια ανεξαρτήτως πλατφόρµας διεπαφή για λειτουργίες συστήµατος. Όλες

οι µεταβλητές και µέθοδοι της είναι static και για το λόγο αυτό δεν µπορεί

να δηµιουργήσει στιγµιότυπα της. Έτσι, η out αποτελεί µεταβλητή κλάσης,

η οποία αντιστοιχεί στη βασική έξοδο (standard output) του συστήµατός σας,

αναφέρεται δε σ’ ένα αντικείµενο που είναι στιγµιότυπο της κλάσης

PrintStream του πακέτου io. Αν ανατρέξετε τώρα στην κλάση PrintStream

θα εντοπίσετε τη µέθοδο στιγµιότυπου println. Είναι ενδιαφέρον να παρα-

τηρήσετε το πώς η υπερφόρτωση διευκολύνει την κλήση της µεθόδου. Ανε-

ξάρτητα από τον τύπο του στοιχείου που θέλετε να τυπώσετε καλείτε την

ίδια println. Το σύστηµα θα αποφασίσει ποιά υλοποίηση θα καλέσει.

Αν απαντήσατε σωστά, σας αξίζουν συγχαρητήρια. Μόλις περάσατε το

δυσκολότερο τεστ αυτού του κεφαλαίου.

1 8 3A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 184: Γλώσσες Προγραμματισμού II

1 8 4 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

4.1

Η έκφραση για των υπολογισµό της τιµής των στοιχείων του πίνακα, θα είναι

x[i] = i + x[i–1], η δε έκφραση για τον τερµατισµό του βρόχου επανάληψης

i<x.length, οπότε και το βασικό τµήµα του κώδικα διαµορφώνεται όπως

παρακάτω:

int x[ ] = new int[10];

x[0] = 0;

for(int i=1; i<x.length; i++)

x[i] = i + x[i–1];

for (int i = 0; i < x.length; i++)

System.out.println(i + ": " + x[i]);

Αν απαντήσατε σωστά µπράβο σας, αν όµως δεν απαντήσατε σωστά, ως προς

την σύνταξη της for, θα πρέπει να ανατρέξετε στο αντίστοιχο κεφάλαιο της

ΘΕ3.4, για να θυµηθείτε την σύνταξη της, όπως και τη σύνταξη των υπό-

λοιπων προτάσεων ελέγχου ροής.

4.2

Circle[] circles = new Circle[12];

for (int i = 0; i < circles.length; i++)

circles[i] = new Circle(point[i], radius[i]);

Μετά τη δήλωση του πίνακα circles από την πρώτη γραµµή του παραπάνω

κώδικα δηµιουργούνται µόνο οι 12 αναφορές σε στιγµιότυπα Circle. Τα

πραγµατικά στιγµιότυπα δηµιουργούνται στη συνέχεια (new) και τα στοι-

χεία του πίνακα αναφέρονται (=) σε αυτά µε την εκτέλεση του βρόχου for.

Αν απαντήσατε σωστά, µπράβο σας, αν όχι θα πρέπει να µελετήσετε µε

περισσότερη προσοχή αυτή τη φορά την υποενότητα 4.1.4. ∆ώστε ιδιαίτερη

προσοχή στον τύπο του πίνακα, είναι ένα από τα πλέον συχνά χρησιµοποι-

ούµενα στοιχεία της Java.

5.1

Αν ονοµάσουµε Client την κλάση του στιγµιότυπου πελάτη και Supplier την

κλάση του στιγµιότυπου προµηθευτή τότε:

1) Tο αντικείµενο–προµηθευτής είναι ορατό στο αντικείµενο πελάτη, όταν

Page 185: Γλώσσες Προγραμματισμού II

η κλάση Client είναι στο ίδιο πακέτο µε την κλάση Supplier[5] π.χ.:

class Supplier

class Client

2) Tο αντικείµενο–προµηθευτής αποτελεί παράµετρο σε κάποια µέθοδο του

αντικειµένου–πελάτη, όταν ισχύουν οι παρακάτω δηλώσεις:

class Supplier

class Client

public m(Supplier s) …..

3) Tο αντικείµενο–προµηθευτής είναι τµήµα του αντικειµένου–πελάτη όταν

ισχύουν οι παρακάτω δηλώσεις:

class Supplier

class Client

Supplier s;

:

4) το αντικείµενο–προµηθευτής είναι ένα τοπικά ορισµένο αντικείµενο σε

µια µέθοδο του πελάτη όταν ισχύουν οι παρακάτω δηλώσεις:

class Supplier

class Client

public m()

Supplier s;

:

Αν η απάντηση σας απέχει κατά πολύ από την παραπάνω, µην ανησυχείτε,

είναι µια δύσκολη άσκηση. Φροντίστε όµως να την κατανοήσετε σε βάθος.

1 8 5A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

[5] Yπάρχουν βέβαια και άλλες περιπτώσεις, τις οποίες όµως θα δούµε στις επόµε-

νες ενότητες.

Page 186: Γλώσσες Προγραμματισμού II

1 8 6 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Αν η απάντηση σας είναι σωστή σας αξίζουν συγχαρητήρια. Κάνατε ένα πολύ

καλό βήµα προς το θέµα της οργάνωσης προγράµµατος που θα µας απα-

σχολήσει στη συνέχεια.

5.2

Μετά τις απαραίτητες δηλώσεις η κλάση C1 διαµορφώνεται όπως παρακάτω:

public class C1

public v1;

private v2;

public m1()

private m2()

m3()

private protected m4()

protected m5()

Αν απαντήσατε σωστά, σας αξίζουν συγχαρητήρια, αν όµως η απάντηση

σας δεν είναι πλήρως σωστή, θα πρέπει να επιµείνετε στην κατανόηση των

προσδιοριστών. Είναι βασικής σηµασίας για την ανάπτυξη αξιόπιστων

προγραµµάτων.

6.1

abstract class Shape

abstract class TwoDimentionalShape extends Shape

abstract class ThreeDimentionalShape extends Shape

class Circle extends TwoDimentionalShape

class Rectangle extends TwoDimentionalShape

class Cube extends ThreeDimentionalShape

class Sphere extends ThreeDimentionalShape

Αν απαντήσατε σωστά µπράβο σας. Ο ορισµός της ιεραρχίας των κλάσεων

είναι µια πολύ βασική ενέργεια σχεδιασµού. Θα δείτε πως καλοσχεδιασµέ-

να αντικειµενοστρεφή συστήµατα έχουν ιεραρχίες κλάσεων, στις οποίες τα

πάνω επίπεδα αποτελούνται από αφηρηµένες κλάσεις.

Page 187: Γλώσσες Προγραμματισμού II

Αν δεν απαντήσατε σωστά, θα πρέπει να δώσετε ιδιαίτερη έµφαση στο θέµα

του ορισµού της ιεραρχίας των κλάσεων. Είναι απαραίτητη προϋπόθεση για

την ανάπτυξη αντικειµενοστρεφούς λογισµικού.

6.2

Οι κλάσεις Circle και Rectangle, κληρονοµούν από την κλάση Shape τις διε-

παφές των µεθόδων area και circumference, για τις οποίες πρέπει να ορίσουν

το σώµα τους και επιπλέον τα πρόσθετα χαρακτηριστικά τους.

public class Circle extends Shape

double r;

static final double PI = 3.14159;

public double area() return PI*r*r;

public double circumference() return 2*PI*r;

public class Rectangle extends Shape

double w,h;

public double area() return w*h;

public double circumference() return 2 * (w+h);

Αν δεν απαντήσατε σωστά, µην ανησυχείτε. Θα πρέπει να δώσετε όµως

περισσότερη έµφαση στην ενότητα 2.4 και να ανατρέξετε στο κεφάλαιο 3,

όπου χρησιµοποιήσαµε επανειληµµένα την κλάση Circle.

Αν απαντήσατε σωστά σας αξίζουν συγχαρητήρια. Συνεχίστε µε τον ίδιο ρυθµό.

6.3

Ο ζητούµενος δηµιουργός έχει την παρακάτω µορφή:

public GraphicCircle(double x, double y, double r, Color

outline, Color fill)

this.x = x; this.y = y; this.r = r;

this.outline = outline;

this.fill = fill;

1 8 7A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 188: Γλώσσες Προγραμματισμού II

1 8 8 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Σηµειώστε ότι δεν αναθέτουµε τιµές µόνο στις µεταβλητές που άµεσα ορί-

ζει η κλάση GraphicCircle, αλλά και σε αυτές που κληρονοµεί από την πρό-

γονο της Circle.

Αν η απάντηση σας δεν µοιάζει µε την παραπάνω, πρέπει «να σας κτυπήσω

το καµπανάκι». Στη φάση αυτή δε θα πρέπει να αντιµετωπίζουµε δυσκολίες

στον ορισµό µεθόδων. Ανατρέξτε στην ενότητα 3.3 και µελετήστε προσε-

κτικά τα περί ορισµού δηµιουργών.

Αν η απάντησή σας είναι σωστή, µπράβο σας! Αποµένει να δούµε τώρα, πώς

θα την βελτιώσουµε, επαναχρησιµοποιώντας τον κώδικα που είχαµε γράψει

για το δηµιουργό της κλάσης Circle.

6.4

Μια πρόταση της µορφής super (…) καλεί το δηµιουργό της προγόνου κλά-

σης, ενώ µια πρόταση της µορφής this (…) καλεί έναν άλλο δηµιουργό της

ίδιας κλάσης.

Αν απαντήσατε σωστά, σας αξίζουν συγχαρητήρια. Είστε πολλοί παρατη-

ρητικοί. Αν όχι, ίσως δεν µελετήσατε όσο θα έπρεπε στα πλαίσια της Άσκη-

σης Αυτοαξιολόγησης την ενότητα 3.3. Είναι καιρός να το κάνετε.

6.5

public GraphicCircle(double x, double y, double r, Color

outline, Color fill)

ssuuppeerr(( xx,, yy,, rr ));;

this.outline = outline;

this.fill = fill;

Πρώτα καλείται ο δηµιουργός της GraphicCircle, ο οποίος καλεί άµεσα δια-

µέσου της super το δηµιουργό της κλάσης Circle µε παραµέτρους x, y και r.

Αυτός µε τη σειρά του καλεί έµµεσα, µε την σύνταξη super() που εισάγει ο

µεταγλωττιστής, το δηµιουργό του Object, που είναι η πρόγονος κλάσης του.

Έτσι εκτελείται πρώτα ο δηµιουργός της Object στη συνέχεια ο δηµιουργός

της Circle και τέλος ο δηµιουργός της GraphicCircle.

Αν η απάντησή σας δεν είναι η σωστή µην ανησυχείτε. Ηταν µια δύσκολη

άσκηση. Αν αντίθετα απαντήσατε σωστά σας αξίζουν θερµά συγχαρητήρια,

τα πάτε πολύ καλά «µε τις κληρονοµιές».

Page 189: Γλώσσες Προγραμματισμού II

6.6

Έκφραση Σηµασία

this.x µεταβλητή x της κλάσης K

x µεταβλητή x της κλάσης L

super.x µεταβλητή x της κλάσης M

((L)this).x η έκφραση δεν έχει νόηµα

super.super.x

((K)this).x

Αν απαντήσατε σωστά µπράβο σας. Αν όχι, θα πρέπει να µελετήσετε πάλι

πιο προσεκτικά τώρα την υποενότητα 6.4.4 που αναφέρεται στις επικαλυ-

πτόµενες µεταβλητές.

6.7

Το αποτέλεσµα της εκτέλεσης του προγράµµατος θα είναι

2

–2

1

–2

Η έκφραση m.x αναφέρεται στην µεταβλητή x της κλάσης Μ και εποµένως

η πρόταση

System.out.println(m.x); θα τυπώσει 2.

Αντίστοιχα η έκφραση m.res() αναφέρεται στην µέθοδο res της κλάσης Μ

και εποµένως η πρόταση

System.out.println(m.res()); θα τυπώσει –2.

Η έκφραση k.x αναφέρεται στην µεταβλητή x της κλάσης K και εποµένως

η πρόταση

System.out.println(k.x); θα τυπώσει 1.

Τέλος η έκφραση k.res() αναφέρεται πάλι στην µέθοδο res της κλάσης Μ

και εποµένως η πρόταση

System.out.println(k.res()); θα τυπώσει –2.

1 8 9A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 190: Γλώσσες Προγραμματισμού II

1 9 0 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Αν δεν απαντήσατε σωστά, µην σας ανησυχεί. Ήταν µια άσκηση στην οποία

ακόµη και καλοί προγραµµατιστές αποτυγχάνουν. Μελετήστε την σε βάθος.

Θα σας βοηθήσει στο ξεκαθάρισµα των εννοιών επικάλυψης και υπερκάλυ-

ψης. Ξαναδιαβάστε παράλληλα και την αντίστοιχη θεωρία.

Αν απαντήσατε σωστά; δεν βρίσκω λόγια να σας συγχαρώ. Πάτε θαυµάσια.

6.8

class K

int i = 1;

int func() return i;

class ª extends K

iinntt ii==33;;

iinntt ffuunncc(())

i = 2 * ssuuppeerr..ii;;

return ssuuppeerr..ffuunncc(()) + i;;

void func2()

System.out.println(ssuuppeerr..ffuunncc(()));;

System.out.println(((((KK))tthhiiss))..ffuunncc(()));;

public class Test1

public static void main(String[] args)

M m = new M();

System.out.println(mm..ii);

System.out.println(((((KK))mm))..ii);

System.out.println( ((((KK))mm))..ffuunncc(()) );

System.out.println( mm..ffuunncc(()) );

m.func2();

// υπερκαλύπτει την func της K

// επικαλύπτει την i της Κ

// καλεί την func της Κ

// καλεί την func της Μ

// αναφέρεται στην i της Μ

// αναφέρεται στην i της Κ

Page 191: Γλώσσες Προγραμματισμού II

Αν η απάντησή σας δεν είναι η σωστή, µην ανησυχείτε. Είναι µια πολύ

δύσκολη άσκηση που µόνο λίγοι έµπειροι προγραµµατιστές θα κατάφερναν.

Είναι όµως µια άσκηση που η µελέτη της, έχει να σας προσφέρει πολλά,

όσον αφορά την υπερκάλυψη µεθόδων, επικάλυψη µεταβλητών, early και

late binding. Μελετήστε την πρόταση προς πρόταση σε συνδυασµό µε την

αντίστοιχη θεωρία.

Αν δώσατε σωστή απάντηση, δύο τινά µπορεί να συµβαίνουν: είτε «πιάνετε

πουλιά στον αέρα», είτε είστε αρκετά τυχερός στις επιλογές σας. Στην τελευ-

ταία αυτή περίπτωση θα σας συνιστούσα για κάθε ενδεχόµενο να µην απο-

φύγετε την επισταµένη µελέτη της άσκησης σε συνδυασµό µε την αντίστοι-

χη θεωρία.

6.9

Έχετε δύο επιλογές. Σύµφωνα µε την πρώτη µπορείτε να δηλώσετε µια

κλάση µε όνοµα π.χ. Const, στην οποία να δηλώσετε όλες τις σταθερές του

πακέτου. Μετά από αυτό θα αναφέρεστε στις σταθερές µε εκφράσεις τις µορ-

φής Const.NUMBER_OF_ITEMS.

Εναλλακτικά, µπορείτε να δηλώσετε µία διεπαφή που θα περιέχει όλες τις

σταθερές και στη συνέχεια να ορίζετε κάθε κλάση που χρησιµοποιεί κάποια

από τις σταθερές να υλοποιεί την διεπαφή. Στην περίπτωση αυτή, η αναφο-

ρά στις σταθερές θα γίνεται µόνο µε το όνοµα της σταθερής, αφού δεν απαι-

τείται η πρόθεση του ονόµατος της διεπαφής.

Αν απαντήσατε σωστά, µπράβο σας! αν όχι µην ανησυχείτε ήταν µια δύσκο-

λη άσκηση.

6.10

Ορίζουµε τη διεπαφή Shape µε τις λειτουργίες area και circumference όπως

παρακάτω:

interface Shape

double area();

double circumference();

Στη συνέχεια ορίζουµε τις δύο κλάσεις Circle και Rectangle να υλοποιούν

την διεπαφή Shape.:

1 9 1A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 192: Γλώσσες Προγραμματισμού II

1 9 2 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

class Circle implements Shape

class Rectangle implements Shape

Μετά τις παραπάνω δηλώσεις τα στιγµιότυπα των κλάσεων Circle και

Rectangle µπορούν να χρησιµοποιηθούν πολυµορφικά, ως προς τις λειτουρ-

γίες που ορίζει η διεπαφή Shape. Στο παρακάτω τµήµα κώδικα υπολογίζεται

η συνολική επιφάνεια και η συνολική περίµετρος δοθέντων στιγµιότυπων

των δύο κλάσεων:

Shapes[] shapes = new Shapes[10];

Circle c1 = new Circle(2,3,1);

Rectangle r1 = new Rectangle(2.0,4.0);

Rectangle r2 = new Rectangle(6.0,8.0);

Circle c2 = new Circle(2,3,1);

shapes[0] = c1; shapes[1] = r1;

shapes[2] = r2; shapes[3] = c2;

double area = 0;

double circumference = 0;

for(int i=0;i<shapes.length;i++)

area += shapes[i].area();

circumference += shapes[i].circumference ();

Όπως παρατηρείτε χρησιµοποιήσαµε τη διεπαφή Shape αντί της abstract κλά-

σης Shape από την οποία κληρονοµούσαν οι κλάσεις Circle και Rectangle.

Αν δεν απαντήσατε σωστά, θα πρέπει να σας επιστήσω την προσοχή στο ότι

χρησιµοποιήσαµε την διεπαφή Shape αντί της abstract κλάσης Shape, από

την οποία οι κλάσεις Circle και Rectangle κληρονοµούσαν τις abstract µεθό-

δους area και circumference (δες Άσκηση Αυτοαξιολόγησης 2). Θα πρέπει

συνεπώς να µελετήσετε µε περισσότερη προσοχή τώρα την υπενότητα 6.4.1

και στη συνέχεια την υποενότητα 6.4.7 για να διαπιστώσετε τις οµοιότητες

αλλά και τις διαφορές που εµφανίζονται στις κατασκευές extends και

implements.

Page 193: Γλώσσες Προγραμματισμού II

Αν απαντήσατε σωστά, µπράβο σας. Η έννοια του πολυµορφισµού είναι

σηµαντικής σηµασίας για την ΑΠ και η κατανόησή της ένα πολύ θετικό

βήµα. Θα σας συνιστούσα όµως για λίγο να σταθείτε στην τελευταία φράση

της παραπάνω παραγράφου.

7.1

Μια πρώτη εκδοχή του διαγράµµατος κλάσεων της Αριθµοµηχανής δίνεται

παρακάτω:

1 9 3A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Calculator

Stack

Memory

OperandOperator

Adder Subtracter Multiplier Divider

Όπως µπορείτε να διακρίνετε έχει καταγραφεί η αφηρηµένη κλάση Operator

της οποίας υποκλάσεις µπορούν να θεωρηθούν οι 5 τελεστές. Έχουν επίσης

καταγραφεί οι σχέσεις κληρονοµικότητας µεταξύ των κλάσεων αυτών, καθώς

και οι σχέσεις συνάθροισης µεταξύ της κλάσης Calculator και των υπολοί-

πων κλάσεων που απαρτίζουν την Αριθµοµηχανή. Χρησιµοποιήθηκε το σύµ-

βολο Æ από την πλευρά του όλου.

Αν δεν καταγράψατε τις σωστές σχέσεις του διαγράµµατος κλάσεων, µην

απελπίζεστε, δεν είναι εύκολη δουλειά. Φροντίστε όµως να κάνετε µια προ-

σεκτική και σε βάθος µελέτη του πρώτου κεφαλαίου του βιβλίου.

Αν το διάγραµµα σας είναι «κοντά» σε αυτό που σας δόθηκε, µπράβο σας.

Κάνατε το σηµαντικότερο βήµα για την ανάπτυξη ενός εύρωστου, επεκτά-

σιµου και ευκολοσυντήρητου προγράµµατος.

7.2

Η περιγραφή της µεθόδου θα έχει την µορφή:

Πάρε από τη στοίβα τον πρώτο τελεστή,

πάρε από τη στοίβα το δεύτερο τελεστή,

Page 194: Γλώσσες Προγραμματισμού II

1 9 4 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

πρόσθεσε τους δυο τελεστές,

βάλε το αποτέλεσµα στη στοίβα.

7.3

Η µέθοδος pop επιστρέφει στιγµιότυπο τύπου Object. Για να χειριστούµε

αυτό το στιγµιότυπο θα πρέπει να το µετατρέψουµε σε τύπου Double. Παρό-

λα αυτά ο τελεστής άθροισης δεν µπορεί να εφαρµοστεί σε αντικείµενα

τύπου Double και εποµένως δεν µπορούµε να προσθέσουµε άµεσα τους δύο

τελεστέους. Προφανώς θα πάρουµε τις double τιµές τους (δες τεκµηρίωση

βιβλιοθήκης), θα τις προσθέσουµε και το αποτέλεσµα θα το κάνουµε αντι-

κείµενο τύπου Double, το οποίο µπορεί να θεωρηθεί Object και να τοποθε-

τηθεί στη στοίβα µε αποστολή σ’ αυτή του κατάλληλου µηνύµατος. Έτσι

έχουµε τον παρακάτω ορισµό για την κλάση Adder, την οποία θεωρούµε

υποκλάση της κλάσης Operator:

class Adder extends Operator

public void operate()

Double d1 = (Double)Calc.s.pop();

Double d2 = (Double)Calc.s.pop();

Double d3 = new Double(d1.doubleValue() +

d2.doubleValue());

Calc.s.push(d3);

ή στην πιο συµπαγή µορφή

class Adder extends Operator

public void operate()

Double d = new Double(((Double)Calc.s.pop()).

doubleValue() +

((Double)Calc.s.pop()).doubleValue());

Calc.s.push(d);

Σηµειώστε ότι η έκφραση Calc.s.pop() είναι στιγµιότυπο τύπου Object. To

µετατρέπουµε (cast) σε τύπου Double και του αποστέλλουµε το µήνυµα

Page 195: Γλώσσες Προγραμματισμού II

doubleValue. H έκφραση που δηµιουργήθηκε ((Double)Calc.s.pop()).double

Value() είναι double και εποµένως µπορεί να εφαρµοστεί πάνω της ο τελε-

στής +. Το αποτέλεσµα της πρόσθεσης, που είναι double, το χρησιµοποιού-

µε σαν όρισµα στον κατάλληλο δηµιουργό της κλάσης Double για την δηµι-

ουργία ενός νέου στιγµιότυπου το οποίο και αποθηκεύουµε στη στοίβα, στην

οποία δεν µπορούµε να αποθηκεύσουµε πρωτογενή τύπο.

Σε κάθε περίπτωση βέβαια θα πρέπει να έχει δοθεί προηγουµένως ο ορισµός

της κλάσης Operator:

abstract class Operator

public abstract void operate();

Αν δεν απαντήσατε σωστά, µην απογοητεύεστε. Ήταν µια πολύ δύσκολη

άσκηση, η οποία όµως, έχει να σας προσφέρει πολλά.

Αν απαντήσατε σωστά, πολλά, πολλά,συγχαρητήρια.

7.4

Μια έκδοση της ζητούµενης κλάσης έχει ως ακολούθως:

class Operand

private double value;

public Operand(double val) value = val;

public void add_digit();

public void deleteLastDigit();

public void reset();

public void set(double val) value = val;

Όπως είδατε ορίσαµε και έναν δηµιουργό µε όρισµα τύπου double ώστε να

έχουµε τη δυνατότητα άµεσου ορισµού της τιµής του τελεστέου, ταυτόχρο-

να µε τη δηµιουργία του. Ο δηµιουργός αυτός θα απλοποιήσει τη διαδικα-

σία ανάπτυξης της πρώτης έκδοσης του προγράµµατος. Μπορούµε να δηµι-

ουργήσουµε έναν τελεστέο µε την επιθυµητή τιµή απλά καλώντας τον

κατάλληλο δηµιουργό και περνώντας του σαν όρισµα την επιθυµητή τιµή.

Επιπλέον ορίσαµε και τη µέθοδο set. Με τη χρήση της µεθόδου αυτής δίνου-

µε νέα τιµή σ’ ένα υπάρχον αντικείµενο µε την αποστολή µηνύµατος της

µορφής set(12.5).

1 9 5A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 196: Γλώσσες Προγραμματισμού II

1 9 6 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Θεωρούµε πως ο τελεστέος έχει την ευθύνη να τοποθετεί το περιεχόµενό του

στη στοίβα, όταν του αποσταλεί το µήνυµα complete. Η αντίστοιχη µέθοδος

θα δηµιουργεί ένα αντικείµενο τύπου Double και θα το τοποθετεί στη στοί-

βα, καθώς αυτή δεν µπορεί να δεχτεί πρωτογενή τύπο αλλά µόνο τύπους

αναφοράς. Ο Operand διαµορφώνεται όπως παρακάτω:

class Operand

// fiˆ˜ Ë ÚÔËÁÔ‡ÌÂÓË ¤Î‰ÔÛË

public void complete()

Double d = new Double(value);

Calc.s.push(d);

reset();

H complete µπορεί να δοθεί σε πιο συµπαγή µορφή

public void complete() Calc.s.push(new

Double(value)); reset();

Εναλλακτικά, και οδηγούµενοι από την υλοποίηση, θα µπορούσαµε να έχου-

µε ονοµάσει τη µέθοδο flush. Ένα όνοµα σαφώς προερχόµενο από το περι-

βάλλον υλοποίησης.

Αν δε δώσατε το σωστό ορισµό της κλάσης Operand, θα πρέπει να κάνετε

µια επανάληψη του κεφαλαίου 3, για να δείτε τον τρόπο ορισµού δεδοµένων

και µεθόδων σε µία κλάση.

Αν απαντήσατε σωστά, µπράβο σας, βάλατε ακόµη ένα «λιθαράκι» για το

«κτίσιµο» της πρώτης έκδοσης της αριθµοµηχανής σας.

7.5

Ο ζητούµενος κώδικας έχει ως ακολούθως:

public static void main(String[] args)

Calc.s = new Stack(); // ‰ËÌÈÔ˘ÚÁ›· ÙÔ˘ ÛˆÚÔ‡

Adder ad = new Adder(); // ‰ËÌÈÔ˘ÚÁ›· ÂÓfi˜ Adder

// ‰ËÌÈÔ˘ÚÁ›· ÂÓfi˜ ·ÚÔ˘ÛÈ·ÛÙ‹ ·ÔÙÂϤÛÌ·ÙÔ˜

ResultPresenter rp = new ResultPresenter();

Page 197: Γλώσσες Προγραμματισμού II

op = new Operand(12.0); // ‰ËÌÈÔ˘ÚÁ›· ÙÂÏÂÛÙ¤Ô˘

// ÌÂ ÙÈÌ‹ 12.0

op.complete(); // ÙÔÔı¤ÙËÛË

// ÙÔ˘ ÙÂÏÂÛÙ‹ ÛÙÔÓ ÛˆÚfi

op.set(4.0); // ·fi‰ÔÛË Ù˘ ÙÈÌ‹˜ 4.0

// ÛÙÔ ÛÙÈÁÌÈfiÙ˘Ô op

op.complete(); // ÙÔÔı¤ÙËÛË

// ÙÔ˘ ÙÂÏÂÛÙ‹ ÛÙÔÓ ÛˆÚfi

ad.operate(); // ÂÓÂÚÁÔÔ›ËÛË

// ÙÔ˘ Adder

rp.operate(); // ÂÓÂÚÁÔÔ›ËÛË ÙÔ˘

// ResultPresenter

Σηµειώστε τη δηµιουργία των κατάλληλων αντικειµένων από τις πρώτες

τρεις γραµµές του κώδικα της main. Ο υπόλοιπος κώδικας περιγράφει την

αλληλεπίδραση των αντικειµένων της εφαρµογής για να έχουµε από αυτή

την ζητούµενη συµπεριφορά.

8.1

Μια τέτοια επιλογή δεν είναι καλή γιατί το συγκεκριµένο catch µπλοκ θα

συλλαµβάνει κάθε εξαίρεση καθιστώντας σχεδόν αδύνατο το χειρισµό των

επιµέρους τύπων.

8.2

To πρώτο catch µπλοκ συλλαµβάνει εξαιρέσεις τύπου ΑΕxception αλλά και

τύπων που υλοποιούνται από κλάσεις απογόνους της ΑΕxception. Αυτό έχει

σαν αποτέλεσµα εξαιρέσεις τύπου ΒΕxception να συλλαµβάνονται και να

αντιµετωπίζονται από το πρώτο catch µπλοκ και όχι από το δεύτερο όπως

προφανώς είναι ο στόχος του συγγραφέα του κώδικα του παραδείγµατος. Το

δεύτερο catch µπλοκ δεν θα ενεργοποιηθεί ποτέ.

Αν δεν απαντήσατε σωστά θα πρέπει να επανέλθετε µε περισσότερη επιµο-

νή στις υποενότητες 8.2.1 και 8.2.2. Είναι απαραίτητο για τη συνέχεια της

µελέτης του κεφαλαίου.

Αν η απάντηση σας είναι σωστή, µπράβο σας.

1 9 7A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 198: Γλώσσες Προγραμματισμού II

1 9 8 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

8.3

Οι εξαιρέσεις στη Java εγείρονται στις παρακάτω περιπτώσεις:

1. Aπό µια πρόταση throws,

2. από µια κλήση µεθόδου που έχει δηλωθεί έτσι ώστε να εγείρει εξαιρέσεις,

3. από προτάσεις που περιέχουν εκφράσεις που µπορεί να εγείρουν µια από

τις προκαθορισµένες RuntimeExceptions της Java. Οι εξαιρέσεις αυτές, που

µπορεί να εγείρονται από κάθε µέθοδο, είναι γνωστές σαν µη ελεγχόµενες

(unchecked), καθώς ο µεταγλωττιστής δε µας ενηµερώνει για την µη σύλ-

ληψη τους.

Για παράδειγµα η έκφραση x/y, όταν το y είναι 0, µπορεί να εγείρει

ArithmeticException, ενώ η arr[y] µπορεί να εγείρει ArrayIndexOutOf

BoundException, όταν το y προσδιορίζει στοιχείο έξω από τα όρια του πίνα-

κα arr.

Αν δε δώσατε την τρίτη περίπτωση δεν πειράζει. Αν όµως δε δώσατε τις δύο

πρώτες περιπτώσεις θα πρέπει να επανέλθετε στη µελέτη της θεωρίας του

κεφαλαίου µέχρι εδώ µε την προσοχή που η δυσκολία των νέων αυτών εννοι-

ών επιβάλλει.

8.4

Η µη ύπαρξη αντικειµένου στη στοίβα αποτελεί εξαίρεση την οποία η pop

θα πρέπει να µεταδώσει στη µέθοδο που την κάλεσε. Η καλούσα µέθοδος µε

τη σειρά της θα πρέπει είτε να συλλάβει την εξαίρεση είτε να τη µεταδώσει.

Οι ενέργειες που θα πρέπει να κάνουµε είναι οι εξής:

1. Να δηλώσουµε µια κλάση StackException, απόγονο της Exception, που

θα αναπαριστά τον τύπο των εξαιρέσεων που µπορεί να προκύψουν στη

στοίβα. Η κλάση θα περιέχει ένα αλφαριθµητικό που θα δίνει λεπτοµέ-

ρειες για την αιτία της εξαίρεσης.

2. Στο σώµα της pop θα πρέπει να περιληφθεί έλεγχος για το αν υπάρχει δια-

θέσιµο αντικείµενο στη στοίβα. Αν δεν υπάρχει θα δηµιουργεί µια εξαί-

ρεση τύπου StackException.

3. Να προσθέσουµε το throws τµήµα στη δήλωση της µεθόδου δηλώνοντας

τον τύπο της εξαίρεσης που η pop θα εγείρει.

Αν η απάντηση σας δεν είναι η σωστή, θα πρέπει να επιµείνετε στη µελέτη

Page 199: Γλώσσες Προγραμματισμού II

και κατανόηση του τρόπου µε τον οποίο χειριζόµαστε τις εξαιρετικές περι-

πτώσεις όταν η γλώσσα προγραµµατισµού υποστηρίζει την τεχνική του χει-

ρισµού εξαιρέσεων.

Αν απαντήσατε σωστά, σας αξίζουν συγχαρητήρια. Η κατανόηση της λογι-

κής του χειρισµού εξαιρέσεων είναι το σηµαντικότερο βήµα για την αποτε-

λεσµατική αξιοποίηση του.

8.5

Η σωστή απάντηση δίνεται στη συνέχεια.

class Stack

….

public void pop() throws StackException

if(isEmpty())

throw new StackException("Õ‰ÂÈ· ÛÙÔ›‚·");

…. //

Το αλφαριθµητικό «Άδεια στοίβα» είναι πλέον η τιµή του αλφαριθµητικού

του αντικείµενου εξαίρεσης και θα χρησιµοποιηθεί κατάλληλα από τον κώδι-

κα αντιµετώπισης της εξαίρεσης.

8.6

H µέθοδος myMethod καλεί την pop, η οποία εγείρει εξαίρεση τύπου

StackException. Έχουµε τις παρακάτω δύο επιλογές:

Α. Η myMethod συλλαµβάνει και αντιµετωπίζει την εξαίρεση, οπότε δια-

µορφώνεται ως ακολούθως:

public void myMethod()

try

// ÎÒ‰Èη˜ Ô˘ ÂÚȤ¯ÂÈ ÎÏ‹ÛË Ù˘ pop

catch (StackException se)

// ÎÒ‰Èη˜ Ô˘ ¯ÂÈÚ›˙ÂÙ·È ÙËÓ ÂÍ·›ÚÂÛË

// StackException

1 9 9A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 200: Γλώσσες Προγραμματισμού II

2 0 0 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Β. Η myMethod δε συλλαµβάνει την εξαίρεση, οπότε, υποχρεωτικά, πρέπει

να τη µεταδώσει στην ιεραρχία κλήσεων. Στην περίπτωση αυτή η δήλωση

της διαµορφώνεται όπως παρακάτω:

public void myMethod() throws StackException

… // ÙÔ ÛÒÌ· Ù˘ ‰ÂÓ ÂÚȤ¯ÂÈ try Î·È catch ÌÏÔΘ

Θα πρέπει βέβαια να προσθέσουµε και την περίπτωση που συλλαµβάνουµε

την εξαίρεση και την αντιστοιχούµε σε µία από τις δικές µας εξαιρέσεις, την

οποία και εγείρουµε. Απαραίτητη προϋπόθεση βέβαια είναι, να έχει δηλω-

θεί η εξαίρεσή µας, στο throws τµήµα της δήλωσης της µεθόδου µας. Σας

συνιστώ να δώσετε ένα παράδειγµα της υβριδικής αυτής περίπτωσης.

Αν δεν απαντήσατε σωστά, θα πρέπει να επανέλθετε στη µελέτη της υποε-

νότητας 8.2.3, την οποία προφανώς δε µελετήσατε ικανοποιητικά.

Αν απαντήσατε σωστά, σας αξίζουν συγχαρητήρια. Φαίνεται πως είστε σε

θέση να χειρίζεστε εξαιρέσεις.

8.7

Ανατρέχοντας στην τεκµηρίωση της βασικής βιβλιοθήκης της Java βλέπου-

µε, πως η NullPointerException, είναι απόγονος της RuntimeException. Αυτό

σηµαίνει, πως δεν είναι απαραίτητο να συλληφθεί.

Όσον αφορά την έξοδο διακρίνουµε τρεις περιπτώσεις:

Α. στο try µπλοκ εγείρεται µια εξαίρεση NullPointerException. H έξοδος έχει

ως ακολούθως:

myMethod Begin

NullPointerException συνελήφθη

NullPointerException αντιµετωπίστηκε

τέλος διαχειριστή εξαιρέσεων

myMethod End

B. στο try µπλοκ εγείρεται µια εξαίρεση που δεν είναι NullPointerException.

H έξοδος έχει ως ακολούθως:

myMethod Begin

µια µη αναµενόµενη εξαίρεση συνελήφθη

Page 201: Γλώσσες Προγραμματισμού II

η εξαίρεση δεν αντιµετωπίστηκε

τέλος διαχειριστή εξαιρέσεων

myMethod End

Γ. στο try µπλοκ δεν εγείρεται εξαίρεση. H έξοδος έχει ως ακολούθως:

myMethod Begin

τέλος διαχειριστή εξαιρέσεων

myMethod End

Προσοχή χρειάζεται στην πρόταση throws µέσα στο catch µπλοκ. Είναι

φανερό πως η αντιµετώπιση της εξαίρεσης δεν εκφράζεται µόνο µε ενέργει-

ες της µεθόδου που περιέχει το catch µπλοκ, αλλά στην προσπάθεια ανά-

κτησης του ελέγχου (recover) µπορεί να γίνει κάποια πρώτη αντιµετώπιση

(π.χ. καθαρισµός πόρων) στα πλαίσια της µεθόδου, και ταυτόχρονα η εξαί-

ρεση να διαδοθεί στην ιεραρχία κλήσεων δίνοντας τη δυνατότητα στον κώδι-

κα που καλεί την myMethod να κάνει τις απαραίτητες ενέργειες.

Αν η απάντηση σας δεν είναι σωστή, δεν έχετε κατανοήσει πλήρως τον µηχα-

νισµό διαχείρισης εξαιρέσεων. Θα πρέπει να µελετήσετε πάλι µε περισσό-

τερη προσοχή την ενότητα 8.2.

Αν δώσατε σωστή απάντηση, σας αξίζουν συγχαρητήρια. Έχετε κατανοήσει

έναν από τους πιο σύνθετους µηχανισµούς ελέγχου ροής της Java.

8.8

Η κλάση myMethod, όπως µπορείτε να παρατηρήσετε, από τον κώδικά της δεν

αντιµετωπίζει τις εξαιρέσεις που δεν είναι τύπου NullPointerException,

αλλά τις εγείρει (δες πρόταση throw e). Η πληροφορία αυτή θα πρέπει να περι-

ληφθεί στη δήλωση της µε το κατάλληλο τµήµα throws. Η δήλωση διαµορ-

φώνεται ως ακολούθως:

static void myMethod(String myString) throws Exception

9.1

∆ηµιουργούµε µια κλάση TreadTest, η οποία δηµιουργεί δύο στιγµιότυ-

πα της κλάσης PingPong και στη συνέχεια τα εκκινεί αποστέλλοντας τους

το µήνυµα start. Στον ενδεικτικό κώδικα που σας δίνουµε παρακάτω µετά

2 0 1A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 202: Γλώσσες Προγραμματισμού II

2 0 2 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

την εκκίνηση των νηµάτων, έχει τοποθετηθεί ένας βρόχος for για να γίνει

εµφανής η παρεµβολή των εξόδων των δύο νηµάτων µε την έξοδο της main.

O ζητούµενος κώδικας έχει ως ακολούθως:

class ThreadTest

public static void main(String [] args)

PingPong ping = new PingPong("PING",30);

PingPong pong = new PingPong("pong",60);

ping.start();

pong.start();

for(int i=0;i<400;i++)

System.out.print(i + " ");

ping.stop();

pong.stop();

Αν ο κώδικάς σας δε µοιάζει µε τον παραπάνω, αν εξαιρέσουµε το for loop,

µην ανησυχείτε. Είναι το πρώτο σας πρόγραµµα µε περισσότερα του ενός

νήµατα. Αν θέλετε όµως να τα πάτε καλύτερα στη συνέχεια, µελετήστε πιο

προσεκτικά µια φορά ακόµη την υπό ενότητα 9.2.1.

Αν ο κώδικας δηµιούργησε δύο νήµατα[6] και τα είδατε να τρέχουν µπράβο

σας! µπήκατε µε επιτυχία στον κόσµο των πολυ–νηµατικών εφαρµογών.

9.2

Η κλάση θα έχει µια µεταβλητή στιγµιότυπου τύπου int και δύο µεθόδους,

µια για αποθήκευση (put) και µια για ανάκτηση (get). O προφανής ορισµός

της έχει ως ακολούθως:

class Buffer

private int value;

public void put(int val) value = val;

public int get() return value;

[6] Στην πράξη έχουµε ακόµη ένα νήµα που το λειτουργικό δηµιούργησε για την

εφαρµογή σας.

Page 203: Γλώσσες Προγραμματισμού II

όπου η µεταβλητή στιγµιότυπου value ορίστηκε private για να εξαναγκάσει

σε πρόσβαση µόνο διαµέσου των µεθόδων.

Αν η απάντηση σας δε συµφωνεί µε την παραπάνω, υποθέτω πως δεν κατα-

νοήσατε το ζητούµενο της άσκησης. Θα χρειαστεί στη συνέχεια να είστε πιο

προσεκτικοί καθώς το θέµα του ταυτοχρονισµού απαιτεί συγκέντρωση.

9.3

Ο παραγωγός θα αναπαρασταθεί από µια κλάση απόγονο της Thread. Θα

έχει σαν µεταβλητή στιγµιότυπου µια αναφορά σε αποθηκευτικό χώρο και

θα ορίζει τον κώδικα που πρέπει να εκτελεί σαν σώµα της µεθόδου run. Ιδι-

αίτερη προσοχή θα πρέπει να αποδοθεί στην κλήση της µεθόδου sleep, που

εγείρει εξαίρεση τύπου InterruptedException την οποία πρέπει να συλλά-

βουµε και αντιµετωπίσουµε.

Η κλάση Producer θα έχει ακόλουθη µορφή:

class Producer extends Thread

private Buffer b;

public Producer(Buffer b)this.b = b;

public void run()

for(int i=0;i<12;i++)

try

Thread.sleep((int)(Math.random() * 3000));

catch(InterruptedException e)

System.err.println(e.toString());

b.put(i);

System.out.println("Producer set buffer to" + i);

Aς σηµειωθεί πως ο δηµιουργός του στιγµιότυπου τύπου Consumer θα πρέ-

2 0 3A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 204: Γλώσσες Προγραμματισμού II

2 0 4 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

πει να περάσει σαν όρισµα µια αναφορά σε αποθηκευτικό χώρο τύπου

Buffer. Στον αποθηκευτικό αυτό χώρο θα αποθηκεύει το παραγόµενο αγαθό

ο παραγωγός.

Αν δεν απαντήσατε σωστά, µην ανησυχείτε. Είναι ίσως η πρώτη σας άσκη-

ση που πρέπει να εισάγετε χειρισµό εξαιρέσεων. Μελετήστε την άσκηση

προσεκτικά και επιχειρήστε να ορίσετε την κλάση του καταναλωτή.

9.4

Με λογική ανάλογη αυτής της δόµησης της περιγραφής της put έχουµε για

τη get:

όσο η αποθήκη είναι άδεια

περίµενε

πάρε το αγαθό

ενηµέρωσε την condition variable ότι η αποθήκη είναι άδεια

ενηµέρωσε τα νήµατα που είναι σε αναµονή χρήσης του αντικειµένου ότι αυτό

είναι πλέον διαθέσιµο

επέστρεψε το αγαθό

Αν η απάντηση σας δεν είναι η σωστή, µη σας στεναχωρεί. Οι έννοιες του

ταυτόχρονου προγραµµατισµού είναι από τη φύση τους σύνθετες και χρειά-

ζεται κάποιος χρόνος για την εµπέδωσή τους. Μην το βάλετε κάτω. Ο επι-

µένων νικά!

Αν απαντήσατε σωστά, µπράβο σας, είστε σε καλό δρόµο.

9.5

Η κλάση Buffer θα διαθέτει εκτός από τη µεταβλητή value και την condition

variable του ελεγκτή, µια boolean µεταβλητή. Το νήµα µπαίνει σε κατάστα-

ση αναµονής καλώντας τη µέθοδο wait, η οποία εγείρει την εξαίρεση

InterruptedException, που πρέπει να συλλάβουµε. Για την ενηµέρωση των

νηµάτων που είναι σε αναµονή χρήσης του αντικειµένου χρησιµοποιείται η

notify. Έτσι η Buffer διαµορφώνεται όπως παρακάτω:

class Buffer

private int value;

private boolean empty = true;

Page 205: Γλώσσες Προγραμματισμού II

public synchronized void put(int val)

while(!empty)

try

wait();

catch(InterruptedException e)

System.err.println("Exception:" +

e.toString());

value = val;

empty = false;

notify();

public synchronized int get()

int value;

while(empty)

try

wait();

catch(InterruptedException e)

System.err.println("Exception:" +

e.toString());

value = this.value;

empty = true;

notify();

return value;

2 0 5A ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ∞ ™ ∫ ∏ ™ ∂ ø ¡ ∞ À ∆ √ ∞ • π √ § √ ° ∏ ™ ∏ ™

Page 206: Γλώσσες Προγραμματισμού II

2 0 6 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Αν ο κώδικάς σας δε µοιάζει σε γενικές γραµµές µε τον παραπάνω, µην

ανησυχείτε. Ισχύουν οι παρατηρήσεις της προηγούµενης άσκησης αυτο-

αξιολόγησης.

Αν ο κώδικας σας είναι σωστός πολλά, πολλά συγχαρητήρια.

Page 207: Γλώσσες Προγραμματισμού II

∂Ó‰ÂÈÎÙÈΤ˜ ∞·ÓÙ‹ÛÂȘ ¢Ú·ÛÙËÚÈÔًوÓ

1.1

Μια πιθανή λίστα κλάσεων και αντίστοιχων στιγµιότυπων θα µπορούσε να

έχει την παρακάτω µορφή

Κλάση Στιγµιότυπο

Ιδιοκτήτης Γιώργος

fast food «fast food ο Γιώργος»

Υπάλληλος Μαίρη, Νίκος

Πελάτης Χρήστος, Κώστας

Τοστιέρα οι δύο τοστιέρες του µαγαζιού

Φούρνος µικροκυµάτων ο φούρνος του µαγαζιού

Πρόσωπο Γιώργος, Μαίρη, Νίκος, Χρήστος,

Κώστας

Θα µπορούσα να έχω καταγράψει επιπλέον τις κλάσεις «Μαγαζί», «Ηλε-

κτρική Συσκευή», «τοστ», κ.ο.κ. Στη φάση αυτή ο στόχος µας δεν είναι µια

πλήρης καταγραφή των κλάσεων. Είναι ενδιαφέρον όµως να παρατηρήσω

ότι ο Γιώργος µπορεί να θεωρηθεί στιγµιότυπο της κλάσης «Ιδιοκτήτης»

αλλά και της κλάσης «Πρόσωπο». Το ίδιο συµβαίνει και µε τα στιγµιότυπα

των κλάσεων «Υπάλληλος» και «Πελάτης», τα οποία µπορούν να θεωρη-

θούν και στιγµιότυπα της κλάσης «Πρόσωπο».

Αν η λίστα σας διαφέρει ριζικά από την παραπάνω, µην ανησυχείτε, ήταν µια

πρώτη επαφή µε τις έννοιες. ∆ιαβάστε όµως πιο προσεχτικά τώρα τη σχετι-

κή θεωρία. Στη συνέχεια, θα έχετε την ευκαιρία να πάτε καλύτερα σε άλλες

παρόµοιες ασκήσεις.

Αν η λίστα σας µοιάζει µε την παραπάνω, µπράβο σας. Μόλις κάνατε µια

από τις πιο δύσκολες δουλειές της διαδικασίας ανάπτυξης ενός συστήµατος,

αυτής της «Αναγνώρισης Αντικειµένων». Θα δείτε στη συνέχεια πως το στά-

διο αυτό είναι πολύ δύσκολο και η επιτυχής έκβασή του προσδιορίζει σε

µεγάλο βαθµό την επιτυχία του έργου της ανάπτυξης του συστήµατος.

Αν η λίστα σας είναι σχεδόν ίδια µε την παραπάνω, σας αξίζουν συγχαρη-

τήρια, σας ταιριάζει πολύ η ΑΠ.

Page 208: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

1.2

Χρησιµοποιώντας συνεχή γραµµή για τη σχέση γενίκευσης–εξειδίκευσης και

διακεκοµµένη για τη σχέση συνάθροισης, διαµορφώνουµε τη παρακάτω

λίστα κλάσεων και των ζητούµενων συσχετίσεων.

Η παραπάνω λίστα δεν καταγράφει όλες τις κλάσεις ούτε όλες τις σχέσεις.

∆ίνεται ενδεικτικά. Η ηλεκτρική συσκευή είναι µια αφηρηµένη έννοια ένα

επίπεδο αφαιρετικότητας, πιο ψηλά από τις αντίστοιχες έννοιες Φούρνος

µικροκυµάτων, Ψυγείο και Τοστιέρα. Συγκεντρώνει τα κοινά χαρακτηριστι-

κά τους, που απορρέουν από την ιδιότητά τους σαν ηλεκτρικές συσκευές. Το

ίδιο συµβαίνει µε την κλάση «fast food» που αποτελεί εξειδίκευση της περισ-

σότερο αφαιρετικής κλάσης «Μαγαζί». Η σχέση µέρους–όλου που συνδέσει

τις κλάσεις «Κτίσµα», «Φούρνος», «Ψυγείο» και «Τοστιέρα» µε την κλάση

«fast food» αναπαριστά το γεγονός ότι οι κλάσεις αυτές αποτελούν συνθε-

τικά (µέρη) του fast food.

Σύµφωνα µε τη σηµειολογία της Unified Modeling Language (UML)[2] [UML

97], η σχέση µεταξύ των κλάσεων αναπαρίσταται µε ένα ευθύγραµµο τµήµα,

το οποίο συνδέει τα ορθογώνια που αναπαριστούν τις κλάσεις. Ειδικότερα,

για τη σχέση γενίκευσης χρησιµοποιείται ένα κλειστό βέλος στην πλευρά της

γενικής κλάσης όπως στην παρακάτω αναπαράσταση της σχέσης γενίκευ-

σης–εξειδίκευσης µεταξύ των κλάσεων ηλεκτρική συσκευή και ψυγείο:

Kλάση

Hλεκτρική συσκευή

Mαγαζί

Fast food

Kλάση

Φούρνος µικροκυµάτων

Ψυγείο

Tοστιέρα

Fast food

Kτίσµα

2 0 8

[2] H UML εισήχθη µόλις το 1997 αλλά έχει γίνει αποδεκτή από την βιοµηχανία

παραγωγής λογισµικού σαν στάνταρτ γραφική γλώσσα για τεκµηρίωση και ανά-

πτυξη συστηµάτων λογισµικού. Πληροφορίες µπορείτε να βρείτε στο UML resource

center στη διεύθυνση http://www.rational.com/uml/index.shtml

Hλεκτρική συσκευή Ψυγείο

Page 209: Γλώσσες Προγραμματισμού II

2 0 9∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

Αν η λίστα σας διαφέρει ριζικά από τη δική µας, µην ανησυχείτε. Ήταν µια

πρώτη επαφή µε καινούργιες έννοιες. ∆ιαβάστε όµως πιο προσεχτικά τώρα

τη σχετική θεωρία, ώστε στη συνέχεια να έχετε την ευκαιρία να τα πάτε

καλύτερα σε άλλες παρόµοιες ασκήσεις.

Αν η λίστα σας µοιάζει µε την παραπάνω, µπράβο σας. Θα δείτε στη συνέ-

χεια πως και το στάδιο αυτό είναι εξ ίσου δύσκολο µε αυτό της αναγνώρι-

σης αντικειµένων και κλάσεων, η δε επιτυχής έκβασή του, προσδιορίζει σε

µεγάλο βαθµό την επιτυχία του έργου της ανάπτυξη του συστήµατος.

Αν η λίστα σας είναι σχεδόν ίδια µε την παραπάνω, σας αξίζουν συγχαρη-

τήρια. Τα πάτε θαυµάσια.

2.1

Το ζητούµενο πρόγραµµα είναι σχεδόν ίδιο µε αυτό του Παραδείγµατος 2.

Είναι προφανές ότι θα πρέπει να αποστείλουµε ένα µήνυµα drawString για

καθένα από τα στοιχεία που θέλουµε να εµφανίσουµε στην οθόνη. Προσο-

χή πρέπει να δοθεί στις τιµές του τρίτου ορίσµατος που ορίζουν την κάθετη

συντεταγµένη σε pixels στην οποία θα τυπωθεί το πρώτο όρισµα. Υποθέτο-

ντας ύψος 12 για την βασική γραµµατοσειρά που χρησιµοποιεί το σύστηµα

χρησιµοποιήσαµε ένα βήµα 15 pixels για κάθε επόµενη γραµµή. Ο κώδικας

θα έχει την παρακάτω µορφή:

// ¢Ú·ÛÙËÚÈfiÙËÙ· 2 – ∆˘ÒÓÔÓÙ·˜ ‰È‡ı˘ÓÛË Û applet

import java.applet.Applet; // οÓÂÈ import ÙËÓ ÎÏ¿ÛË

// Applet

import java.awt.Graphics; // οÓÂÈ import ÙËÓ ÎÏ¿ÛË

// Graphics

public class SecondApplet extends Applet

// ∏ ̤ıÔ‰Ô˜ ÂÌÊ·Ó›˙ÂÈ ÙÔ applet.

Για τη σχέση συνάθροισης αντίστοιχα, χρησιµοποιείται ένας µικρός ρόµβος

στην πλευρά της κλάσης «όλου», όπως στην παρακάτω αναπαράσταση της

σχέσης µέρους–όλου µεταξύ των κλάσεων κτίσµα και fast food:

Fast food Kτίσµα

Page 210: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

// ∏ ÎÏ¿ÛË Graphics ˘ÔÛÙËÚ›˙ÂÈ ÙȘ ·ÂÈÎÔÓ›ÛÂȘ ÛÙË

Java.

public void paint(Graphics g)

g.drawString("£Ú·ÌÔ˘Ï›‰Ë˜", 50, 50);

g.drawString("∫Ï¿Óı˘", 50, 65);

g.drawString("∂ÚÁ·ÛÙ‹ÚÈÔ ∏/À", 50, 80);

Σηµειώστε ότι, αφού το όνοµα της κλάσης είναι SecondApplet, αυτό θα πρέ-

πει να είναι και το όνοµα του αρχείου που θα περιέχει τον πηγαίο κώδικά σας.

Αν ο κώδικάς σας διαφέρει ως προς τις συντεταγµένες εκτύπωσης, µην ανη-

συχείτε. Θα πρέπει ίσως να σας υπενθυµίσω ότι το σύστηµα συντεταγµένων

της Java έχει όπως παραπλεύρως, µε τις συντεταγµένες εκφρασµένες σε

pixels. H δε drawString τυπώνει τον πρώτο χαρακτήρα πάνω και δεξιά από

το σηµείο που ορίζουν οι συντεταγµένες.

2.5

Όπως θα διαπιστώσατε ήρθε η ώρα να χρησιµοποιήσετε τις µεθόδους της

Graphics που αναζητήσατε στην ∆ραστηριότητα 1. Ο κώδικας που πρέπει

να περιέχεται στο αρχείο drawShapes.java[3] θα έχει την παρακάτω µορφή

// ¢Ú·ÛÙËÚÈfiÙËÙ· 3 – ∑ˆÁÚ·Ê›˙ÔÓÙ·˜ Û¯‹Ì·Ù·.

import java.applet.Applet; // οÓÂÈ import ÙËÓ ÎÏ¿ÛË

// Applet

import java.awt.Graphics; // οÓÂÈ import ÙËÓ ÎÏ¿ÛË

// Graphics

public class drawShapes extends Applet

public void paint(Graphics g)

g.drawLine(10,20,110,170);

g.drawRect(10,20,100,150);

g.drawOval(10,20,100,150);

2 1 0

Hello(x, y)

0 +x

+y

0

[3] Ή όποιο άλλο όνοµα έχετε χρησιµοποιήσει, απλά προσέξτε να έχει το ίδιο όνοµα

και η κλάση που αναπαριστά το πρόγραµµά σας.

Page 211: Γλώσσες Προγραμματισμού II

2 1 1∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

Αν το πρόγραµµά σας δεν εµφανίζει στην οθόνη τα ζητούµενα, όπως στο

παραπλεύρως σχήµα, πιθανότατα αυτό οφείλεται σε κακή χρήση των

µεθόδων της Graphics, σε συνδυασµό µε το σύστηµα συντεταγµένων της

Java. Μην ανησυχείτε. Θα πρέπει όµως να εξασφαλίσετε καλή πρόσβαση

στην τεκµηρίωση της βασικής βιβλιοθήκης και να προσαρµοστείτε µε τον

τρόπο παρουσίασης των µεθόδων, καθώς και µε το σύστηµα συντεταγµέ-

νων της Java. Είναι πολύ απαραίτητο για τη οµαλή συνέχιση της προσπά-

θειάς σας στην ΑΠ.

Αν πετύχατε το στόχο, συγχαρητήρια. Τα πάτε πολύ καλά και µε την βασι-

κή βιβλιοθήκη της Java και αυτό είναι πολύ σηµαντικό.

3.2

Μια αντικειµενοστρεφής έκδοση σε δοµηµένα Ελληνικά µπορεί να έχει την

παρακάτω µορφή:

¢‹ÏˆÛË Ù˘ ÎÏ¿Û˘ Ô˘ ·Ó··ÚÈÛÙ¿ ÙÔ ÚfiÁÚ·ÌÌ·

̤ıÔ‰Ô˜ main //ÔÚ›˙ÂÈ ÙËÓ ·ÓÙ›‰Ú·ÛË ÙÔ˘ ÚÔÁÚ¿ÌÌ·ÙÔ˜

// ÛÙÔ Ì‹Ó˘Ì· ‘run’

‰ËÌÈÔ‡ÚÁËÛ ۈÚfi s

ηıfiÛÔÓ Ë ÂÈÏÔÁ‹ ÙÔ˘ ¯Ú‹ÛÙË ‰ÂÓ Â›Ó·È ‘Ù¤ÏÔ˜’

Â¿Ó Ë ÂÈÏÔÁ‹ ›ӷÈ

‘ÂÈÛ·ÁˆÁ‹’

‚¿Ï ÛÙÔÈ¯Â›Ô //Ì‹Ó˘Ì· s.push() ÛÙÔ

//ÛˆÚfi Ó· ‚¿ÏÂÈ ÛÙÔȯ›Ô

‘ÂÍ·ÁˆÁ‹’

‚Á¿Ï ÛÙÔÈ¯Â›Ô //Ì‹Ó˘Ì· s.pop() ÛÙÔ ÛˆÚfi

//Ó· ‚Á¿ÏÂÈ ÛÙÔȯ›Ô

‘ηı·ÚÈÛÌfi˜’

ηı¿ÚÈÛ ÙÔ ÛˆÚfi //Ì‹Ó˘Ì· s.clear() ÛÙÔ

//ÛˆÚfi Ó· ηı·Ú›ÛÂÈ

¢‹ÏˆÛË Ù˘ ÎÏ¿Û˘ Ô˘ ·Ó··ÚÈÛÙ¿ ÙÔ ÛˆÚfi

Είναι σηµαντικό ότι αναπαριστούµε το πρόγραµµα µε µια κλάση, η οποία θα

Page 212: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

πρέπει να έχει ορισµένη τη µέθοδο main που προσδιορίζει τη συµπεριφορά

του προγράµµατος στο µήνυµα «τρέξε», που θα του στείλετε διαµέσου του

λειτουργικού συστήµατος. Πρώτη δουλειά της main; Φυσικά η δηµιουργία

ενός στιγµιότυπου τύπου σωρού. Θυµόσαστε, «για να φάτε ζεστή τυρόπιτα

πρέπει να υπάρχει ένα fast food». Στη συνέχεια δέχεται την επιλογή του χρή-

στη και ενεργεί ανάλογα. ∆εν θα πρέπει βέβαια να παραλείψετε τον ορισµό

της κλάσης που αναπαριστά το σωρό.

Αν ο σκελετός σας είναι σε γενικές γραµµές ίδιος µε τον παραπάνω Μπρά-

βο σας! Μόλις δώσατε την δοµή του πρώτου αντικειµενοστρεφούς προ-

γράµµατος σας, κάτι πολύ σηµαντικό.

Αν ο κώδικάς σας δεν περιείχε τη δήλωση της κλάσης του σωρού, µικρό το

πρόβληµα αλλά θα πρέπει να είστε πιο προσεκτικοί. Λάθη αυτής της µορφή

εξ άλλου εντοπίζονται και αναφέρονται από το µεταγλωττιστή.

Αν ο κώδικάς σας διαφέρει ριζικά από το παραπάνω µην απογοητεύεστε. Θα

πρέπει όµως να ξαναδιαβάσετε πιο προσεχτικά τώρα, τις Ενότητες 3.1 και

3.2 του κεφαλαίου.

3.3

Μια αναπαράσταση µπορεί να έχει την παρακάτω µορφή:

class Rectangle

private int x1,y1; //·Ó··Ú¿ÛÙ·ÛË ¿Óˆ ·ÚÈÛÙÂÚ‹˜

ÎÔÚ˘Ê‹˜

private int x2,y2; //·Ó··Ú¿ÛÙ·ÛË Ù˘ ‰È·ÁÒÓÈ·

·¤Ó·ÓÙÈ ÎÔÚ˘Ê‹˜

public Rectangle(int x1, int y1, int x2, int y2)

this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2

= y2;

public double area() return (x2–x1) * (y2–y1);

public double circumference() return 2* ((x2–x1) +

(y2–y1));

2 1 2

Page 213: Γλώσσες Προγραμματισμού II

2 1 3∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

∆ηλώνοντας τις συντεταγµένες σαν private εµποδίζουµε την πρόσβαση σ’

αυτές έξω από την κλάση Rectangle. Σηµειώστε τη χρήση του τελεστή this.

Σας επιτρέπει να αναφερθείτε, µέσα από το σώµα του δηµιουργού, στα δεδο-

µένα του στιγµιότυπου, όταν τα ορίσµατα του δηµιουργού έχουν ίδια ονό-

µατα µε τα δεδοµένα της κλάσης.

Μία εναλλακτική αναπαράσταση όπου χρησιµοποιούµε µία κορυφή και το

πλάτος και ύψος του ορθογωνίου έχει τη µορφή:

class Rectangle

private int x,y; // ·Ó··Ú¿ÛÙ·ÛË ¿Óˆ

// ·ÚÈÛÙÂÚ‹˜ ÎÔÚ˘Ê‹˜

private int w,h; // ·Ó··Ú¿ÛÙ·ÛË ÙÔ˘

// Ï¿ÙÔ˘˜ Î·È ‡„Ô˘˜

public Rectangle(int x, int y, int w, int h)

this.x = x; this.y = y; this.w = w; this.h = h;

public double area() return w * h;

public double circumference() return 2* (w + h);

Όπως βλέπετε χρησιµοποιήσαµε δηµιουργό µε ορίσµατα τα x, y, w και h.

Έτσι, αν θέλουµε να δηµιουργήσουµε στιγµιότυπο έχοντας τα x1, y1, και x2,

y2, θα πρέπει να καλέσουµε το δηµιουργό ως εξής:

Rectangle r = new Rectangle(x1, y1, x2–x1, y2–y1);

Θα σας προβληµάτισε ίσως η µονάδα µέτρησης της επιφάνειας και της περι-

µέτρου, καθώς οι συντεταγµένες είναι εκφρασµένες σε pixels. ∆ε µας ενδια-

φέρει στα πλαίσια της άσκησης, αλλά προφανώς υποψιάζεστε ότι πρέπει να

έχουµε µια αντιστοίχιση των cm σε pixels, ώστε να µπορούµε να αναπαρα-

στήσουµε και υπολογίσουµε σωστά ορθογώνια εκφρασµένα σε cm.

Τέλος, µια ακόµη καλύτερη αναπαράσταση, µπορεί να δηλώνει σαν δεδοµέ-

να τα δύο σηµεία των διαγώνια απέναντι κορυφών, µε την προϋπόθεση

βέβαια ότι έχετε ορίσει την κλάση σηµείο. Αλλά αυτό θα το δούµε σε επό-

µενη δραστηριότητα, κάντε λίγο υποµονή.

Page 214: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

3.4

Μια έκδοση του ζητούµενου προγράµµατος δίνεται στη συνέχεια:

1 // ¢Ú·ÛÙËÚÈfiÙËÙ· 4 – ÀÔÏÔÁÈÛÌfi˜ ÂÈÊ¿ÓÂÈ·˜ Î·È ÂÚÈ

// ̤ÙÚÔ˘ ÔÚıÔÁˆÓ›Ô˘

2 public class RectTest

3 public static void main(String[] args)

4 Rectangle r = new Rectangle(20,20,60,80);

//‰ËÌÈÔ˘ÚÁ›· ÛÙÈÁÌÈfiÙ˘Ô˘ r ÌÂ

//Ù·˘Ùfi¯ÚÔÓË ·fi‰ÔÛË ·Ú¯ÈÎÒÓ ÙÈÌÒÓ

5

6 System.out.println("ÂÚ›ÌÂÙÚÔ˜:

"+r.circumference());

7 System.out.println("ÂÈÊ¿ÓÂÈ·:" +r.area() +

"\n");

8

9

10

11 class Rectangle

12 private int x1,y1,x2,y2;

13 public rectangle(int x1, int y1, int x2, int y2)

this.x1=x1; this.y1= y1;w = x2–x1;h = y2–y1;

14 // ÏÔȤ˜ ‰ËÏÒÛÂȘ

15

Όπως βλέπετε το πρόγραµµά µας αποτελείται από δύο κλάσεις, τη RectTest

που αναπαριστά το πρόγραµµα και τη Rectangle που αναπαριστά το ορθο-

γώνιο. Η µέθοδος main, που ορίζει τη συµπεριφορά του προγράµµατός σας

στο µήνυµα «run», πρέπει να είναι ορατή έξω από την κλάση και γι’ αυτό

δηλώνεται σαν public. Έχει δε, σαν έργο, τη δηµιουργία ενός στιγµιότυπου

ορθογωνίου που αναπαριστά το δοθέν ορθογώνιο (γραµµή 4) και στη συνέ-

χεια την εκτύπωση (System.out.println) των ζητούµενων στοιχείων, τα οποία

δέχεται σαν αποκρίσεις του r στα µηνύµατα circumference και area που του

2 1 4

Page 215: Γλώσσες Προγραμματισμού II

2 1 5∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

αποστέλλει (γραµµές 6,7). Μη σας απασχολεί προς το παρόν η λέξη κλειδί

static. Θα την συναντήσουµε αργότερα.

Προσέξτε ότι συµπεριλάβαµε το δηµιουργό της πρώτης έκδοσης της ∆ρα-

στηριότητας 3 σαν πιο κατάλληλο και ότι τα αποτελέσµατά σας είναι σε

pixels και τετραγωνικά pixels αν κάτι τέτοιο έχει νόηµα.

Αν δεν τα καταφέρατε µε το πρόγραµµα, µην ανησυχείτε, είναι ένας νέος

τρόπος σκέψης και οργάνωσης της λύσης. Για να εξοικειωθείτε όµως µ’

αυτόν, θα πρέπει να επανέλθετε, µε µεγαλύτερη επιµέλεια αυτή τη φορά, στη

µελέτη της ενότητας 3.2 και των υποενοτήτων 3.3.1 και 3.3.2, δίνοντας ιδι-

αίτερη έµφαση στην ∆ραστηριότητα 3.

Αν τα καταφέρατε µε το πρόγραµµα, µπράβο σας, µόλις αναπτύξατε το

πρώτο δικό σας αντικειµενοστρεφές πρόγραµµα.

3.5

Θεωρούµε το σηµείο σαν αντικείµενο µε ενσωµατωµένη συµπεριφορά στο

µήνυµα πρόσθεσης σηµείων και ορίζουµε την αντίστοιχη κλάση µ’ ένα δηµι-

ουργό που αντιστοιχεί στην συνάρτηση makepoint.:

class Point

public int x,y;

public Point(int x, int y) this.x = x; this.y = y;

public void addpoint(Point p) //ÚÔÛı¤ÙÂÈ ÙÔ

//ÛËÌÂ›Ô p ÛÙÔ

//ÛÙÈÁÌÈfiÙ˘Ô Ô˘

//‰¤¯ÂÙ·È ÙÔ Ì‹Ó˘Ì·

x += p.x;

y += p.y;

Αντίστοιχα, η έννοια «ορθογώνιο» µπορεί να αναπαρασταθεί από µια κλάση

που έχει σαν δεδοµένα τα σηµεία των δύο διαγώνια απέναντι κορυφών του

και δύο µεθόδους: α) για τον έλεγχο αν δεδοµένο σηµείο βρίσκεται µέσα στο

ορθογώνιο και β) για την κανονικοποίηση των συντεταγµένων του. Μια

τέτοια αναπαράσταση µπορεί να έχει την παρακάτω µορφή:

class Rect

Page 216: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

ppuubblliicc PPooiinntt pp11,, pp22;;

public Rect(Point p1, Point p2) this.p1 = p1;

this.p2 = p2;

public Rect(int x1, int y1, int x2, int y2)

p1 = new Point(x1,y1); p2 = new Point(x2,y2);

public boolean ptinrect(Point p1)

return(p1.x>this.p1.x &&

p1.x<this.p2.x &&

p1.y>this.p1.y && p1.y <

this.p2.y);

public void canonrect()

Ιδιαίτερη προσοχή απαιτείται στον ορισµό των δηµιουργών. Ας τον σχολιά-

σουµε λίγο. Η κλάση Rect έχει σαν δεδοµένα δύο αναφορές σε στιγµιότυπα

Point. Ο πρώτος δηµιουργός βάζει τις αναφορές p1 και p2 στα δύο σηµεία

που αποτελούν τα πραγµατικά ορίσµατα του δηµιουργού. Είχαµε λοιπόν δύο

στιγµιότυπα σηµεία και δηµιουργήσαµε µ’ αυτά ένα ορθογώνιο, για το οποίο

τα δύο σηµεία είναι πλέον συνθετικά του.

Ο δεύτερος δηµιουργός ίσως σας παραξενεύει λίγο, θα προτιµούσατε ίσως

τον κατά πολύ απλούστερο που δίνεται παρακάτω:

public Rect(int x1, int y1, int x2, int y2)

p1.x = x1; p1.y = y1; p2.x = x2; p2.y = y2;

Η δήλωση αυτή εκ πρώτης όψης είναι σωστή. Μάλιστα ο µεταγλωττιστής, δεν

αναγνωρίζει κανένα λάθος. Αλλά στο χρόνο εκτέλεσης, όταν ο διερµηνευτής

εκτελέσει κλήση του δηµιουργού θα αναφέρει λάθος και θα διακόψει την εκτέ-

λεση του προγράµµατος. ∆οκιµάστε το. Προσέξτε πολύ το σηµείο αυτό. Είναι

ένα λάθος που κάνουν όλοι οι νέοι, και όχι µόνο, προγραµµατιστές σε ΑΠ.

Το πρόβληµα δηµιουργείται γιατί το p1 όπως και το p2 είναι απλά αναφο-

ρές, οι οποίες δε δείχνουν σε κανένα στιγµιότυπο, γιατί απλά κανείς δεν τις

έβαλε να δείχνουν, και εποµένως δεν έχουν νόηµα οι εκφράσεις πρόσβασης

των συντεταγµένων. Πρέπει λοιπόν, να φροντίσουµε, ώστε µία από τις πρώ-

τες δουλειές του δηµιουργού να είναι η δηµιουργία δύο στιγµιότυπων τύπου

Point, και µόνο µετά από αυτό µπορούµε να αποδώσουµε τιµές στις συντε-

2 1 6

Page 217: Γλώσσες Προγραμματισμού II

2 1 7∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

ταγµένες τους. Αυτό ακριβώς κάνει ο δεύτερος των δηµιουργών της Rect

εκµεταλλευόµενος τους κατάλληλους δηµιουργούς της Point.

Εάν θέλουµε τώρα να δηµιουργήσουµε το ορθογώνιο, όχι µε τα σηµεία p1

και p2, αλλά µε άλλα που απλά θα έχουν ίδιες µε αυτά συντεταγµένες (µε

κλώνους των p1 και p2 δηλαδή), η δήλωση του δηµιουργού θα διαµορφω-

θεί όπως παρακάτω:

public Rect(Point p1, Point p2)

this.p1 = new Point(p1.x,p1.y);

this.p2 = new Point(p2.x,p2.y);

Αν ο κώδικάς σας διαφέρει από τα παραπάνω ως προς τον αριθµό των κλά-

σεων καθώς και ως προς τα δεδοµένα και τις µεθόδους, που η κάθε κλάση

περιλαµβάνει (όχι τα σώµατα των µεθόδων), είναι ανησυχητικό. Είτε δεν

έχετε κατανοήσει τις βασικές έννοιες της ΑΠ οπότε θα πρέπει να διαβάσετε

κάπως προσεκτικότερα το κεφάλαιο 1 και την ενότητα 3.2, είτε δεν είστε

αρκετά προσεκτικοί και αναθέσατε µεθόδους σε λάθος κλάσεις. Αν έχετε

αναθέσει τη µέθοδο ptinrect στην κλάση point, δεν είναι λάθος, είναι µια εξ

ίσου καλή εναλλακτική επιλογή, η δε δήλωση της έχει την παρακάτω µορφή

public boolean ptinrect(Rect r)

return(x>r.p1.x && x<r.p2.x &&

y>r.p1.y && y < r.p2.y);

Αν ο κώδικάς σας διαφέρει από τον παραπάνω στην υλοποίηση των µεθό-

δων, µην σας ανησυχεί, θα χρειαστεί όµως να διορθώσετε τον κώδικά σας

ώστε να είναι διαθέσιµος για επόµενη δραστηριότητα.

Αν ο κώδικάς σας είναι σχεδόν ίδιος µε τον παραπάνω, εξαιρώντας ίσως τους

δηµιουργούς της Rect, σας αξίζουν συγχαρητήρια, κάνατε πολύ καλή δου-

λειά. Αν πάλι καταφέρατε να ορίσετε σωστά και τους δηµιουργούς της Rect,

«Ε! Τι να πω; Τα πηγαίνετε θαυµάσια».

3.6

Αναπτύξτε το πρόγραµµα σταδιακά σε ελεγχόµενα βήµατα. Για παράδειγµα,

δηλώστε στην αρχή µόνο την κλάση που αναπαριστά το πρόγραµµά σας και

την Point. ∆ηµιουργήστε τα ζητούµενα στιγµιότυπα και ελέγξτε την ορθό-

τητα του προγράµµατός σας χρησιµοποιώντας προτάσεις της µορφής

System.out.println("p1.x:" + p1.x + "\tp1.y:" + p1.y);

Page 218: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Σε επόµενο βήµα ορίστε την κλάση Rect και δηµιουργήστε τα ζητούµενα

στιγµιότυπα. ∆ιαπιστώστε την δηµιουργία τους µε προτάσεις της µορφής:

System.out.println("r1.p1.x:" + r1.p1.x + "\tr1.p1.y:"

+ r1.p1.y + "\tr1.p2.x:" + r1.p2.x

+ "\tr1.p2.y:" + r1.p2.y );

Σ’ ένα τελευταίο βήµα, χρησιµοποιήστε την ptinrect για να διαπιστώσετε αν

ένα σηµείο βρίσκεται σε δεδοµένο ορθογώνιο.

Στη συνέχεια δίνεται µια έκδοση του ζητούµενου προγράµµατος:

// ¢Ú·ÛÙËÚÈfiÙËÙ· 6

public class RectTest6

public static void main(String[] argv)

Point p1 = new Point(60,60);

Point p2 = new Point(20,30);

Point p3 = new Point(20,70);

Point p4 = new Point(40,50);

Rect r1 = new Rect(10,20,50,60);

Rect r2 = new Rect(30,40,80,80);

System.out.println("p1 in:" +(r1.ptinrect(p1)?

"r1":" ")+(r2.ptinrect(p1)?"\tr2":" "));

System.out.println("p2 in:" +(r1.ptinrect(p2)?

"r1":" ")+(r2.ptinrect(p2)?"\tr2":" "));

System.out.println("p3 in:" +(r1.ptinrect(p3)?

"r1":" ")+(r2.ptinrect(p3)?"\tr2":" "));

System.out.println("p4 in:" +(r1.ptinrect(p4)?

"r1":" ")+(r2.ptinrect(p4)?"\tr2":" "));

class Point

public int x,y;

public Point(int x, int y) this.x = x; this.y = y;

2 1 8

Page 219: Γλώσσες Προγραμματισμού II

2 1 9∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

public Point(Point p1,Point p2) x = p1.x + p2.x; y =

p1.x + p2.x;

public void addpoint(Point p) // ÚÔÛı¤ÙÂÈ ÙÔ ÛËÌ›Ô

// p ÛÙÔ ÛÙÈÁÌÈfiÙ˘Ô Ô˘ ‰¤¯ÂÙ·È ÙÔ Ì‹Ó˘Ì·

x += p.x;

y += p.y;

class Rect

public Point p1, p2;

public Rect(int x1, int y1, int x2, int y2)

p1 = new Point(x1,y1); p2 = new Point(x2,y2);

public boolean ptinrect(Point p1)

return(p1.x>this.p1.x && p1.x<this.p2.x &&

p1.y>this.p1.y && p1.y < this. p2.y);

public void canonrect() [4]

Ήταν µια δύσκολη άσκηση, αν δεν τα καταφέρατε θα πρέπει να επιµείνετε

στη µελέτη του κεφαλαίου 3. Θα σας συνιστούσα, να διαβάσετε επιπλέον

µια φορά τα κεφάλαια 1 και 2 επιµένοντας στα κρίσιµα σηµεία. Θα δείτε ότι

θα σας βοηθήσει στο ξεκαθάρισµα ορισµένων εννοιών.

Αν πετύχατε και αυτό το στόχο, µπράβο σας, τα πάτε θαυµάσια. Ένα γρήγο-

ρο ξεφύλλισµα των κεφαλαίων 1 και 2 θα είναι χρήσιµο και για σας. Θα δείτε

ορισµένες έννοιες µε µάτι προγραµµατιστή ΑΠ.

[4] ΄Oπως βλέπετε δεν σας δίνεται ο κώδικας της canonrect(), είστε σε θέση να τον

δώσετε µόνοι σας.

Page 220: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

4.1

Είναι προφανές ότι ο πηγαίος κώδικας της άσκησης υποθέτει πως τα x, y και

r της κλάσης Circle είναι δηλωµένα public και πως υπάρχει ορισµένος ο

δηµιουργός Circle(double x, double y, double r).

Η πρόταση c2 = c1; βάζει την αναφορά c2 να δείχνει στο αντικείµενο που

δείχνει η αναφορά c1. Η πρόταση c1.r = 4.0; αλλάζει την τιµή της ακτίνας

του αντικειµένου που δείχνει η c1, αλλά το ίδιο αντικείµενο δείχνει και η c2.

Σαν αποτέλεσµα η πρόταση

System.out.println("c2.x:"+c2.x + " c2.y:"+ c2.y + "

c2.r:"+ c2.r);

στη δεύτερη εµφάνιση της, θα δώσει σαν έξοδο

c2.x: 2.0 c2.y:2.0 c2.r:4.0.

Κάτι ανάλογο δε συµβαίνει µε τους πρωτογενείς τύπους και η πρόταση x =

4.0; αλλάζει την τιµή της x, αλλά όχι και την τιµή της y, όπως δείχνει η πρό-

ταση

System.out.println("x:" + x + " y:" + y);

η οποία θα δώσει σαν έξοδο

x:4.0 y:1.0.

4.2

Αν s1 είναι το στιγµιότυπο µε περιεχόµενο «Hello», για να δηµιουργήσουµε

στιγµιότυπο µε τιµή «Hello World» θα πρέπει να προσθέσουµε στο s1 το «

World». Κάτι τέτοιο δεν µπορεί να γίνει άµεσα, γιατί όπως ήδη αναφέραµε

τα στιγµιότυπα της κλάσης String είναι αµετάβλητα. Έτσι δηµιουργούµε ένα

στιγµιότυπο της StringBuffer µε το περιεχόµενο του s1, στο στιγµιότυπο αυτό

προσθέτουµε (append) το « World» και στη συνέχεια δηµιουργούµε ένα νέο

αντικείµενο µε το περιεχόµενο του διαµορφωθέντος στιγµιότυπου της

StringBuffer. Τέλος, αναθέτουµε στην αναφορά s1 να δείχνει το νέο αντι-

κείµενο. Και το αντικείµενο στο οποίο έδειχνε το s1 πριν; Λογικά, θα ανα-

ρωτηθείτε. Μη σας απασχολεί είναι δουλειά του «σκουπιδιάρη» (garbage

collector). Ο κώδικας θα έχει ως κατωτέρω:

public class unit4Test1

public static void main(String[] args)

2 2 0

Page 221: Γλώσσες Προγραμματισμού II

2 2 1∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

String s1 = new String("Hello ");

System.out.println("s1:"+ s1);

StringBuffer buf1 = new StringBuffer(s1);

// ‰ËÌÈÔ˘ÚÁԇ̠¤Ó· ÛÙÈÁÌÈfiÙ˘Ô StringBuffer

buf1.append(" World"); //ÙÔ˘ ÚÔÛı¤ÙÔ˘Ì ÙÔ

//"world"

s1 = new String(buf1);

System.out.println("s1:"+ s1);

Αν ο κώδικας σας δεν µοιάζει µε τον παραπάνω, δεν πειράζει. Φροντίστε

όµως να εξοικειωθείτε µε τη βιβλιοθήκη κλάσεων της Java και µε την τεκ-

µηρίωση της. ∆εν µπορείτε να κάνετε κάτι αξιόλογο χωρίς αυτή.

Αν τα καταφέρατε, µπράβο σας. Συνεχίστε όµως, αυτοσχεδιάζοντας και

εµπλουτίζοντας το πρόγραµµά σας µε χρήση άλλων µεθόδων και από τις δύο

κλάσεις. Θα σας κάνει καλό.

4.3

Οι τελεστές & και | όταν εφαρµόζονται στους ακέραιους τύπους εκτελούν

τις δυαδικές AND και OR λειτουργίες, ενώ όταν εφαρµόζονται σε τύπους

boolean, εκτελούν λογικές AND και OR λειτουργίες. Υλοποιούν δε την

εφαρµοστική σειρά υπολογισµού και όχι την περιορισµένης έκτασης (short

circuit evaluation).

Αντίθετα οι τελεστές && και || εκτελούν περιορισµένης έκτασης AND και

OR δυαδική ή λογική λειτουργία ανάλογα µε τον τύπο των τελεστέων.

Αν δεν απαντήσατε σωστά αυτό πιθανότατα οφείλεται στο ότι δεν έχετε πρό-

σβαση σε ένα από τα βιβλία της βιβλιογραφίας για την Java. Μια τέτοια πρό-

σβαση είναι απαραίτητη, καθώς η περιορισµένη έκταση αλλά και ο στόχος

του βιβλίου δεν επιτρέπει την πλήρη κάλυψη της Java.

Page 222: Γλώσσες Προγραμματισμού II

2 2 2 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

5.1

Όπως θα θυµάστε ο ορισµός της κλάσης κύκλος µας απασχόλησε σε µεγά-

λο βαθµό στο κεφάλαιο 3. Αν δεν δώσατε σωστά τον ορισµό της, σηµαίνει

πως δεν είστε ώριµοι αρκετά για να προχωρήσετε την µελέτη του κεφαλαί-

ου. Θα χρειαστεί να ανατρέξετε πάλι στο κεφάλαιο 3 και να µελετήσετε προ-

σεκτικά κάθε σηµείο του, που έχει σχέση µε τον ορισµό της κλάσης κύκλος,

κατανοώντας τα διαδοχικά βήµατα από τα οποία περάσαµε για να φτάσου-

µε στον τελικό ορισµό της.

Αν δώσατε τον ορισµό της κλάσης κύκλος συµπεριλαµβάνοντας µάλιστα και

τον ορισµό ενός τουλάχιστο δηµιουργού, µπράβο σας! Η µελέτη σας άρχισε

να αποδίδει.

6.1

Υπάρχει µια τάση από µεριάς κληρονοµικότητας να καταστρέψει την από-

κρυψη της ενθυλακωµένης πληροφορίας, εκθέτοντας µέρος της στις απογό-

νους κλάσεις. Αυτό σηµαίνει ότι για την κατανόηση µιας κλάσης που συµ-

µετέχει σε δένδρο ιεραρχίας δεν είναι αρκετό να µελετήσεις τον ορισµό της,

αλλά είναι απαραίτητο να µελετήσεις και όλες τις προγόνους κλάσεις της.

Πολλές φορές µάλιστα, η µελέτη αυτή πρέπει να περιλαµβάνει και το εσω-

τερικό των κλάσεων και είναι πιο επίπονη, καθώς το βάθος ιεραρχίας αυξά-

νει. Είναι καλή τεχνική να αποφεύγετε τη δηµιουργία δένδρων ιεραρχίας

µεγάλου βάθους, επειδή µε τον τρόπο αυτό µειώνετε το βαθµό αναγνωσιµό-

τητας των προγραµµάτων σας.

7.2

Μια πιθανή λίστα µε αντικείµενα από τα οποία αποτελείται η αριθµοµηχα-

νή µας είναι:

• Αριθµοµηχανή (Calculator)

• Τελεστής άθροισης (Adder)

• Τελεστής αφαίρεσης (Subtracter)

• Τελεστής πολλαπλασιασµού (Multiplier)

• Τελεστής διαίρεσης (Divider)

• Τελεστής εµφάνισης αποτελέσµατος (ResultPresenter)

• Τελεστέος (Operator)

• Μνήµη (Memory)

Page 223: Γλώσσες Προγραμματισμού II

Στα παραπάνω αντικείµενα της φάσης της ανάλυσης θα συµπεριλάβουµε και

τη στοίβα (Stack), που αποτελεί αντικείµενο της φάσης σχεδιασµού. Στα

αντικείµενα αυτά θα µπορούσε να περιληφθεί και η έκφραση (Expression),

αν επιλέγαµε αρχικά τη διαµόρφωση της έκφρασης και στη συνέχεια τον

υπολογισµό της τιµής της.

Aς σηµειωθεί ότι αντικείµενα όπως πλήκτρο και οθόνη δεν έχουν θέση στη

φάση αυτή. Αποτελούν αντικείµενα του χώρου επίλυσης του προβλήµατος,

καθώς έχουν άµεση σχέση µε την προτεινόµενη υλοποίηση. Για παράδειγµα

µια αριθµοµηχανή που θα επικοινωνούσε µε το χρήστη µε ήχο δε θα διέθε-

τε τα αντικείµενα αυτά.

Αν δεν απαντήσατε σωστά, µην απελπίζεστε. Είναι µια πολύ δύσκολη άσκη-

ση που απαιτεί εµπειρία στην διαδικασία της ανάλυσης.

Αν απαντήσατε σωστά, σας αξίζουν πολλά συγχαρητήρια.

7.3

Μια ενδεικτική απάντηση έχει ως ακολούθως:

import java.util.*;

import java.lang.*;

public class Calc

public static Stack s;

public static Adder add;

public static ResultPresenter rp;

public static Operand op;

public static void main(String[] argv)

s = new Stack(); // ‰ËÌÈÔ˘ÚÁ›· ÙÔ˘ ÛˆÚÔ‡

ad = new Adder(); // ‰ËÌÈÔ˘ÚÁ›· ÂÓfi˜ Adder

// ‰ËÌÈÔ˘ÚÁ›· ÂÓfi˜ ·ÚÔ˘ÛÈ·ÛÙ‹ ·ÔÙÂϤÛÌ·ÙÔ˜

rp = new ResultPresenter();

op = new Operand(12.0); // ‰ËÌÈÔ˘ÚÁ›· ÙÂÏÂÛÙ¤Ô˘

// ÌÂ ÙÈÌ‹ 12.0

2 2 3∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

Page 224: Γλώσσες Προγραμματισμού II

2 2 4 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

op.complete(); // ÙÔÔı¤ÙËÛË ÙÔ˘ ÙÂÏÂÛÙ‹

// ÛÙÔÓ ÛˆÚfi

op.set(4.0); // ·fi‰ÔÛË Ù˘ ÙÈÌ‹˜ 4.0

op.complete(); // ÙÔÔı¤ÙËÛË ÙÔ˘ ÙÂÏÂÛÙ‹

// ÛÙÔÓ ÛˆÚfi

ad.operate(); // ÂÓÂÚÁÔÔ›ËÛË ÙÔ˘ Adder

rp.operate(); // ÂÓÂÚÁÔÔ›ËÛË ÙÔ˘

// ResultPresenter

abstract class Operator

public abstract void operate();

class Adder extends Operator

……

class ResultPresenter extends Operator

public void operate()System.out.println(Calc.s. pop());

class Operand

…..

Η δεύτερη πρόταση import είναι προϋπόθεση για την χρήση του τύπου Double.

H πρώτη αυτή έκδοση έχει σαν αποτέλεσµα την εµφάνιση του αθροίσµατος

των 12.0 και 4.0. Και µη µου πείτε πως υπάρχει ευκολότερος τρόπος να το

υπολογίσετε.

Αν η απάντηση σας δεν µοιάζει µε την παραπάνω, θα πρέπει να µελετήσετε

τον κώδικα που σας δίνεται ώστε να τον κατανοήσετε πλήρως. Είναι απα-

ραίτητο για την παραπέρα µελέτη του κεφαλαίου.

Page 225: Γλώσσες Προγραμματισμού II

7.4

Μια έκδοση του ζητούµενου προγράµµατος έχει ως ακολούθως:

import java.util.*;

import java.lang.*;

public class Calc

public static Stack s;

public static Adder add;

public static Subtracter sub;

public static Multiplier mul;

public static Divider div;

public static Equals eq;

public static Operand op;

public static void main(String[] argv)

s = new Stack();

add = new Adder();

sub = new Subtracter();

mul = new Multiplier();

div = new Divider();

eq = new Equals();

op = new Operand();

// Make some calculations

double d1 = 12.0;

double d2 = 4.0;

// addition

op.set(d1); op.flush(); op.set(d2); op.flush();

add.operate();

System.out.print(d1 + " + " + d2 + " = ");

eq.operate();

2 2 5∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

Page 226: Γλώσσες Προγραμματισμού II

2 2 6 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

// Sub

op.set(d1); op.flush(); op.set(d2); op.flush();

sub.operate();

System.out.print(d1 + " – " + d2 + " = ");

eq.operate();

// mul

op.set(3.0); op.flush(); op.set(7.0);

op.flush();

mul.operate();

eq.operate();

// Division

op.set(d1); op.flush(); op.set(d2); op.flush();

div.operate();

System.out.print(d1 + " / " + d2 + " = ");

eq.operate();

class Operand

private double value;

public void add_digit();

public void set(double val) value = val;

public void flush() Double d = new Double(value);

Calc.s.push(d);

abstract class Operator

public abstract void operate();

class Adder extends Operator

public void operate()

Double d = new Double(((Double)Calc.s.pop()).double

Value() + ((Double)Calc.s.pop()).doubleValue());

Page 227: Γλώσσες Προγραμματισμού II

Calc.s.push(d);

class Subtracter extends Operator

public void operate()

Double d2 = (Double)Calc.s.pop();

Double d = new Double(((Double)Calc.s.pop()).

doubleValue() –

d2.doubleValue());

Calc.s.push(d);

class Multiplier extends Operator

public void operate()

Double d = new

Double(((Double)Calc.s.pop()).doubleValue()

* ((Double)Calc.s.pop()).doubleValue());

Calc.s.push(d);

class Divider extends Operator

public void operate()

Double d2 = (Double)Calc.s.pop();

Double d = new

Double(((Double)Calc.s.pop()).doubleValue()

/d2.doubleValue());

Calc.s.push(d);

class Equals extends Operator

public void operate()

System.out.println(Calc.s.pop());

2 2 7∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

Page 228: Γλώσσες Προγραμματισμού II

2 2 8 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

Αν ο κώδικάς σας δε µοιάζει µε τον παραπάνω, µην ανησυχείτε. Eίναι δύσκο-

λη άσκηση. Μελετήστε την όµως και προσπαθήστε να επέµβετε για µικρές

τροποποιήσεις. Για παράδειγµα ελέγξτε για διαίρεση δια του µηδενός.

Αν απαντήσατε σωστά σας αξίζουν πολλά, πολλά συγχαρητήρια.

7.5

Ένα ενδεικτικό πρόγραµµα για τον έλεγχο της κλάσης Operand έχει ως ακο-

λούθως:

import java.util.*;

import java.lang.*;

public class Calc

public static Operand op;

public static Stack s;

public static ResultPresenter rp;

public static void main(String[] args)

Calc.s = new Stack();

Operand op = new Operand();

ResultPresenter rp = new ResultPresenter();

op.addDigit('1');

op.addDigit('8');

op.addDigit('2');

op.addDigit('1');

op.complete();

rp.operate(); // ÂÓÂÚÁÔÔ›ËÛË ÙÔ˘ ResultPresenter

class Operand

// fiˆ˜ ÂÓfiÙËÙ· 7.4

Page 229: Γλώσσες Προγραμματισμού II

abstract class Operator

public abstract void operate();

class ResultPresenter extends Operator

public void operate()System.out.println(Calc.s.pop());

7.6

Μια έκδοση του ζητούµενου προγράµµατος έχει ως ακολούθως:

class Operand

private StringBuffer buf;

private double value;

public Operand()

buf = new StringBuffer(14);

public Operand(double val)

this();

buf.append(Double.toString(val));

public void addDigit(char ch)buf.append(ch);;

public void deleteLastDigit()

String s =new String(buf);

buf = new StringBuffer(s.substring(0,s.length()–1));

;

public void reset()buf = new StringBuffer(14);

public void set(double val)

reset();

buf.append(val);

2 2 9∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

Page 230: Γλώσσες Προγραμματισμού II

2 3 0 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

public void complete()

Double d = new Double(buf.toString());

Calc.s.push(d);

reset();

Είναι εµφανές ότι απαιτείται χρήση µεθόδων της κλάσης StringBuffer της

βασικής βιβλιοθήκης.

8.1

Μια έκδοση του ζητούµενου προγράµµατος δίνεται παρακάτω:

import java.io.*;

public class ExceptionTest14

public static void main(String [] args)

try

System.out.println("\nmyMethod(klea)");

myMethod("klea");

System.out.println("\nmyMethod(kleanthis)");

myMethod("kleanthis");

System.out.println("\nmyMethod(null)");

myMethod(null);

catch(Exception e)

System.out.println("main Exception handler");

static void myMethod(String myString) throws Exception

// ÛÒÌ· ÌÂıfi‰Ô˘

Page 231: Γλώσσες Προγραμματισμού II

Aς σηµειωθεί ότι η κλήση της myMethod από τη main πρέπει να γίνει µέσα

σε try µπλοκ. Στην τρίτη κλήση της myMethod χρησιµοποιούµε σαν πραγµα-

τικό όρισµα το null για να προκαλέσουµε την έγερση εξαίρεσης τύπου

NullPointerException. Εκτελέστε το πρόγραµµα για να ελέγξετε την έξοδο του.

9.1

Το πρόγραµµά µας θα αναπαρασταθεί από την κλάση ProducerConsumer της

οποίας η µέθοδος main θα αντλεί τις παρακάτω ενέργειες:

θα δηµιουργεί έναν αποθηκευτικό χώρο τύπου Buffer,

θα δηµιουργεί ένα νήµα παραγωγού,

θα δηµιουργεί ένα νήµα καταναλωτή,

θα ενεργοποιεί τα δύο νήµατα.

Αν η κλάση σας δεν κάνει τις παραπάνω ενέργειες, µην προχωρήσετε στη

µελέτη της απάντησης µας. Κάντε µια διακοπή και προσπαθήστε να ορίσε-

τε µε Java την κλάση ProducerConsumer, όπως περιγράφεται παραπάνω.

Όταν το κάνετε, επανέλθετε για να συγκρίνετε τον κώδικα σας µ’ αυτόν που

σας δίνουµε στη συνέχεια:

public class ProducerConsumer

public static void main(string()argv)

Buffer b = new Buffer();

Producer p = new Producer(b);

Consumer c = new Consumer(b);

p.start();

c.start();

Αν ο κώδικας σας δε µοιάζει µε τον παραπάνω, αρχίζω να ανησυχώ. Μελε-

τήστε µε περισσότερη προσοχή την ενότητα 9.2. Θα δείτε πως έπρεπε να

οδηγηθείτε σε σωστό αποτέλεσµα.

Αν η απάντηση σας είναι η ζητούµενη, σας αξίζουν συγχαρητήρια. Μόλις

αναπτύξατε την πρώτη σας πολυ–νηµατική εφαρµογή.

2 3 1∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

Page 232: Γλώσσες Προγραμματισμού II

2 3 2 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

9.2

Μέρος της εξόδου µιας εκτέλεσης του προγράµµατος που δόθηκε στα πλαί-

σια της δραστηριότητας 1 δίνεται στη συνέχεια:

Producer set buffer to 0

Producer set buffer to 1

Consumer retrieved 1

Consumer retrieved 1

Consumer retrieved 1

Producer set buffer to 2

Consumer retrieved 2

Producer set buffer to 3

Consumer retrieved 3

Consumer retrieved 3

Consumer retrieved 3

Producer set buffer to 4

Producer set buffer to 5

Είναι εµφανές ότι, χωρίς συγχρονισµό µεταξύ παραγωγού και καταναλωτή,

έχουµε τα παρακάτω δύο προβλήµατα:

1. O παραγωγός παράγει και αποθηκεύει νέο αγαθό (Producer set buffer to

1) πριν ο καταναλωτής καταναλώσει το προηγούµενο αγαθό (0).

2. O καταναλωτής καταναλώνει αγαθό χωρίς να µεσολαβήσει αντίστοιχη

παραγωγή µε αποτέλεσµα να καταναλώνει δύο φορές το ίδιο αγαθό

(Consumer retrieved 1, Consumer retrieved 1)

9.3

Αρκεί στον πηγαίο κώδικα που προέκυψε από τη δραστηριότητα 1 να αντι-

καταστήσουµε την κλάση Buffer µε τη νέα έκδοση που προέκυψε από την

άσκηση αυτοαξιολόγησης 5.

Μέρος του αποτελέσµατος δίνεται στη συνέχεια:

Page 233: Γλώσσες Προγραμματισμού II

Producer set buffer to 0

Consumer retrieved 0

Producer set buffer to 1

Consumer retrieved 1

Producer set buffer to 2

Consumer retrieved 2

Producer set buffer to 3

Consumer retrieved 3

Producer set buffer to 4

Consumer retrieved 4

Producer set buffer to 5

Consumer retrieved 5

Producer set buffer to 6

Consumer retrieved 6

….

Είναι εµφανές ότι ο συγχρονισµός επιτεύχθηκε, και ο καταναλωτής κατανα-

λώνει µόνο και εφόσον υπάρχει είναι διαθέσιµο αγαθό, ο δε παραγωγός

παράγει νέο αγαθό µόνο, όταν δεν υπάρχει διαθέσιµο.

2 3 3∂ ¡ ¢ ∂ π ∫ ∆ π ∫ ∂ ™ ∞ ¶ ∞ ¡ ∆ ∏ ™ ∂ π ™ ¢ ƒ∞ ™ ∆ ∏ ƒ π √ ∆ ∏ ∆ ø ¡

Page 234: Γλώσσες Προγραμματισμού II

BÈ‚ÏÈÔÁÚ·Ê›· ÂÏÏËÓÈ΋

[1] [Ben 98]

M.Ben–Ari «Ταυτόχρονος Προγραµµατισµός» Prentice Hall International,

1998. Ελληνική µετάφραση από τον Κλειδάριθµο.

[2] [Horowitz 84]

«Βασικές αρχές γλωσσών προγραµµατισµού» Εκδόσεις Κλειδάριθµος

1993.

Το βιβλίο είναι µετάφραση της δεύτερης Αµερικάνικης έκδοσης του

«Fundamentals of Programming Languages» του Ellis Horowitz,

Computer Science Press, 1984. Αποτελεί µια πολύ καλή και κατά τα

γνωστά µου µοναδική στην Ελληνική γλώσσα πηγή αναφορικά µε τις

βασικές αρχές των γλωσσών προγραµµατισµού. Το βιβλίο είναι κατάλ-

ληλο για ανάγνωση µόνο επιλεκτικών τµηµάτων από σπουδαστές που

µαθαίνουν την πρώτη τους γλώσσα προγραµµατισµού. Είναι όµως απα-

ραίτητο για σπουδαστές που γνωρίζουν και έχουν χρησιµοποιήσει εκτε-

ταµένα µια τουλάχιστο γλώσσα προγραµµατισµού.

BÈ‚ÏÈÔÁÚ·Ê›· ÍÂÓfiÁψÛÛË

[1] [Deitel 98]

Deitel & Deitel «Java: How to program», Second edition, Prentice

Hall International 1998.

Το βιβλίο είναι ένα από τα καλύτερα κείµενα για την Java, εισάγοντας

ταυτόχρονα και τις βαςικές έννοιες του Αντικειµενοστρεφούς Προ-

γραµµατισµού, αλλά και γενικότερα προγραµµατισµού υπολογιστών.

Αν και δεν προϋποθέτει εµπειρία σε προγραµµατισµό και εποµένως µπο-

ρεί να χρησιµοποιηθεί από αρχάριους σε προγραµµατισµό, µπορεί ταυ-

τόχρονα να χρησιµοποιηθεί και από καλούς προγραµµατιστές της C και

C++ για εκµάθηση της Java. Το βιβλίο είναι κατάλληλο και για επαγ-

γελµατίες προγραµµατιστές, καθώς αφιερώνει ένα µεγάλο µέρος του

στην βιβλιοθήκη κλάσεων της γλώσσας δίνοντας πολλά και καλά παρα-

δείγµατα χρήσης της.

[2] [Anuff 96]

Anuuf Ed, «The Java Sourcebook» John Wiley and Sons Inc. 1996.

Page 235: Γλώσσες Προγραμματισμού II

2 3 5B π µ § π √ ° ƒ∞ º π ∞ ∂ § § ∏ ¡ π ∫ ∏ / • ∂ ¡ √ ° § ø ™ ™ ∏

[3] [Booch 94]

Grady Booch, «Object–Oriented Analysis and Design with applications»

second edition, Benjamin/Cummings Publishing Company Inc, 1994.

Αποτελεί ένα από τα καλύτερα βιβλία στο χώρο της Aντικειµενοστρε-

φούς Προσέγγισης. Η σηµαντική του συµβολή είναι κύρια στη φάση του

σχεδιασµού για την οποία κατά την γνώµη µου αποτελεί και το καλύτε-

ρο από τα διαθέσιµα βιβλία. Ο Booch εξ άλλου, µε τον Jacobson και τον

Rumbaugh, είναι οι δηµιουργοί της Unified Modeling Language (UML)

της πρώτης γλώσσας που έγινε πρότυπο για αντικειµενοστρεφή ανά-

πτυξη συστηµάτων.

[4] [Dijkstra 68]

Dijkstra, E.W.: «Co–operating sequential processes» In F.Genuys (Ed.),

Programming Languages: NATO Advanced Stydy Institute. Academic

Press 1968, London, 43–112.

[5] [Flanagan 96]

David Flanagan, «Java in a Nutshell», O’Reilly and Associates Inc.,

1996.

Το βιβλίο καλύπτει στο πρώτο µέρος τα βασικά στοιχεία της γλώσσας

και αφιερώνει το δεύτερο και µεγαλύτερο στο API της Java µε πολλά

παραδείγµατα στον τρόπο χρήσης των εξυπηρετήσεών του. Αποτελεί

κατά τη γνώµη µου ένα από τα καλύτερα βιβλία για τη Java.

[6] [Gosling 96]

Ken Arnold, James Gosling, «The Java Programming Language»,

Addison Wesley, 1996.

Το βιβλίο αποτελεί µια πολύ καλή και σχετικά σύντοµη αναφορά στη

γλώσσα καλύπτοντας τα βασικά στοιχεία και αποφεύγοντας κουραστι-

κές πολυλογίες. Στα θετικά του είναι ότι ο ένας εκ των δύο των συγ-

γραφέων του, ο James Gosling θεωρείται ο πρωτεργάτης της οµάδας

ανάπτυξης της γλώσσας στα εργαστήρια της Sun.

[7] [Hoare 74]

C.A.R. Hoare «Monitors:An operating System Structuring concept»

Communications of the ACM, vol.17, No.10, Oct. 74 pp 549–557.

Page 236: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I2 3 6

[8] [IEEE 1983]

Richard Thayer, M.Dorfman «Systems and Software Requirements

Engineering» IEEE Computer Society Press 1983, Tutorial.

[9] [Jacobson 92]

Ivar Jacobson, «Object–Oriented Software Engineering – A use case

Driven Approach», Addison–Wesley 1992.

Αποτελεί ένα από τα καλύτερα βιβλία στο χώρο της αντικειµενοστρε-

φούς προσέγγισης. Έγινε περισσότερο γνωστό από την έννοια του «use

case» (περίπτωσης χρήσης) που εισήγαγε στη διαδικασία ανάλυσης του

συστήµατος και η οποία υιοθετήθηκε από το σύνολο σχεδόν των µεθο-

δολογιών Aντικειµενοστρεφούς Aνάπτυξης συστηµάτων λογισµικού.

Αναφέρεται κυρίως στις φάσεις της ανάλυσης και σχεδιασµού, οι οποί-

ες αποτελούν αντικείµενο άλλης θεµατικής ενότητας. Ανήκει στα βιβλία

που δεν θα πρέπει να λείπουν από την βιβλιοθήκη του επαγγελµατία στο

χώρο της ανάπτυξης συστηµάτων.

[10] [Kernighan 88]

Η δεύτερη έκδοση του βιβλίου «The C Programming Language»

Prentice Hall κυκλοφόρησε το 1988 καλύπτοντας πλέον την ANSI C.

[11] [Martin 92]

J. Martin, J. Odell, «Object Oriented Analysis & Design» Prentice Hall

1992.

Το βιβλίο αυτό δίνει απόψεις, οι οποίες σε πολλές περιπτώσεις είναι δια-

φορετικές από τις ευρέως θεωρούµενες στον χώρο της Aντικειµενο-

στρεφούς Προσέγγισης. Στις απόψεις αυτές αποφύγετε να ανατρέξετε

στο παρόν στάδιο, γιατί µπορεί να σας δηµιουργήσουν σύγχυση. Αντί-

θετα, οι απόψεις αυτές µπορούν να αποτελέσουν πηγή προβληµατισµού

στο στάδιο που θα έχετε κατανοήσει και χρησιµοποιήσει αρκετά την

ΑΠ. Η παρατήρηση αυτή δεν ισχύει για το κεφάλαιο 3, στο οποίο γίνε-

ται η παραποµπή.

[12] [Meyer 88]

Bertrand Meyer «Object–Oriented Software Construction», Prentice Hall

International, 1988.

Μια πολύ καλή και σε βάθος αναφορά στην ΑΠ χρησιµοποιώντας την

Page 237: Γλώσσες Προγραμματισμού II

2 3 7B π µ § π √ ° ƒ∞ º π ∞ ∂ § § ∏ ¡ π ∫ ∏ / • ∂ ¡ √ ° § ø ™ ™ ∏

αντικειµενοστρεφή γλώσσα Eiffel.

[13] [Rumbaugh 91]

J. Rumbaugh, et.al «Object–Oriented Modeling and Design» Prentice

Hall International, 1991.

Αποτελεί το κλασικό, θα έλεγα, βιβλίο στο οποίο η αντικειµενοστρεφής

προσέγγιση οφείλει την εξάπλωση της. Σαν βασικό εγχειρίδιο της OMT

(Object Modeling Technique) µεθοδολογίας, της περισσότερο χρησιµο-

ποιούµενης µεθοδολογίας πριν την εµφάνιση της UML, είναι αποδεκτό

για την απλότητα µε την οποία εισάγει τις βασικότερες έννοιες της ΑΠ.

Αν και πολλά από τα στοιχεία που παρουσιάζει αποτελούν πλέον παρελ-

θόν για την ΑΠ, όπως το functional model, παρόλα αυτά χρησιµοποιεί-

ται σαν αναφορά για τις βασικές έννοιες της αντικειµενοστρεφούς προ-

σέγγισης όπως links, associations, aggregation, inheritance, dynamic

modeling, κ.λπ.

[14] [Sethi 97]

Ravi Sethi, «Programming Languages: Concepts and Constructs» 2nd

Edition, Addison Wesley 1996. Reprinted with corrections April 1997.

[15] [Sun 95]

James Gosling, Henr McGilton, «The Java Language Environment – A

White Paper» SUN Microsystems 1995.

[16] [Sutherland 95]

Jeff Sutherland «Smalltalk, C++ and OO COBOL: The good the bad

and the ugly», OBJECT MAGAZINE May 95.

[17] [UML 97]

«Unified Modeling Language: UML semantics» version 1.1, Rational

Software, September 97.

[18] [Wilkinson 95]

Nancy Wilkinson «Using CRC cards: An informal Approach to

Object–Oriented Development» SIGS Books 1995, AT&T Bell

Laboratories

[19] [Winder 98]

Rusel Winder, Graham Roberts, «Developing Java Software», John

Page 238: Γλώσσες Προγραμματισμού II

° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I2 3 8

Wiley & Sons, 1998.

Το βιβλίο εισάγει βασικές έννοιες του αντικειµενοστρεφούς προγραµ-

µατισµού χρησιµοποιώντας πολυάριθµα παραδείγµατα. Το βασικό στοι-

χείο που το διαφοροποιεί από την πληθώρα των βιβλίων που αναφέρο-

νται στην Java είναι η ιδιαίτερη έµφαση που δίνει στο σχεδιασµό προ-

γράµµατος µε στόχο την ανάπτυξη εύρωστων (robust) και αξιόπιστων

(reliable) εφαρµογών. Εκτός αυτού το βιβλίο µπορεί να χρησιµοποιηθεί

και σαν αναφορά στην Java, καθώς καλύπτει επιτυχώς µε πολλά µικρά

παραδείγµατα όλα τα χαρακτηριστικά της γλώσσας.

Page 239: Γλώσσες Προγραμματισμού II

°ÏˆÛÛ¿ÚÈ ŸÚˆÓ

abstract Λέξη–κλειδί της Java που επιτρέπει τη δήλωση αφη-

ρηµένων µεθόδων και αφηρηµένων κλάσεων.

abstraction Aφαιρετικότητα.

actor Aντικείµενο που ενεργεί πάνω σ’ άλλα αντικείµενα,

αλλά ποτέ δεν εξυπηρετεί άλλα αντικείµενα.

Ada Σύνθετη γλώσσα προγραµµατισµού για ανάπτυξη

κύρια ενσωµατωµένου (embedded) λογισµικού. Σχε-

διάστηκε έτσι ώστε να υποστηρίζει βασικές αρχές

του Software Engineering όπως reliability, portability,

modularity, reusability, efficiency, maintainability,

information hiding, abstract data types, concurrent

programming, object–oriented programming.

agent Aντικείµενο που ενεργεί πάνω, αλλά και παρέχει εξυ-

πηρετήσεις σε άλλα αντικείµενα.

aggregation Συνάθροιση.

applet Java πρόγραµµα που συνήθως αποθηκεύεται σ’ ένα

αποµακρυσµένο υπολογιστή, στον οποίο οι χρήστες

συνδέονται µε τη χρήση ενός Web browser για να το

κατεβάσουν και να το εκτελέσουν σαν κοµµάτι µιας

ιστοσελίδας.

association Συσχέτιση.

base class Βασική κλάση.

boolean Πρωτογενής τύπος της Java µε δύο δυνατές τιµές:

true και false. ∆εν µπορεί να µετατραπεί (cast) από

και σε άλλους τύπους.

byte Πρωτογενής τύπος της Java. Εύρος τιµών από –128

έως 127. Μπορεί να µετατραπεί (cast) σ’ άλλους

αριθµητικούς τύπους.

bytecode H γλώσσα που κατανοεί και εκτελεί ο διερµηνευτής

της Java. Στη γλώσσα αυτή µεταγλωττίζει ο µετα-

γλωττιστής της Java τον κώδικα Java.

Page 240: Γλώσσες Προγραμματισμού II

2 4 0 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

C++ Γλώσσα αντικειµενοστρεφούς προγραµµατισµού που

αναπτύχθηκε από τον Bjarne Stroustrup στα Bell Labs

στις αρχές της δεκαετίας του 80. Η γλώσσα αποτελεί

επέκταση της C για την υποστήριξη των εννοιών του

αντικειµενοστρεφούς παραδείγµατος.

class Kλάση.

class diagram ∆ιάγραµµα κλάσεων.

class method Mέθοδος κλάσης.

class variable Mεταβλητή κλάσης.

CLOS Συντοµογραφία του Common Lisp Object System.

Είναι το τµήµα της Common Lisp που άµεσα εµπλέ-

κεται µε τις βασικές έννοιες του ΑΠ.

compatibility Συµβατότητα.

constructor ∆ηµιουργός.

correctness Oρθότητα.

coupling Eξάρτηση µεταξύ µονάδων ενός µοντέλου.

CRC Σύντµηση του Class/Responsibility/Collaboration.

derived class Παραγόµενη κλάση. Συνώνυµο: υποκλάση.

dynamic binding ∆υναµική διασύνδεση.

early binding Πρώιµη διασύνδεση.

Eiffel Σύστηµα ανάπτυξης αντικειµενοστρεφούς λογισµι-

κού. Περιλαµβάνει γλώσσα προγραµµατισµού, µεθο-

δολογία και ένα πλήρες γραφικό περιβάλλον ανά-

πτυξης.

encapsulation Eνθυλάκωση.

exception Eξαίρεση.

exception handling Xειρισµός εξαιρέσεων.

extendibility Eπεκτασιµότητα.

extends Λέξη–κλειδί που χρησιµοποιείται στον ορισµό µιας

κλάσης για να προσδιορίσει την πρόγονο κλάση της.

Page 241: Γλώσσες Προγραμματισμού II

final Προσδιοριστής της Java που µπορεί να εφαρµοστεί

σε κλάσεις, µεθόδους και κατηγορήµατα. Μια final

κλάση δεν µπορεί να κληρονοµηθεί. Μια final µέθο-

δος δεν µπορεί να υπερφορτωθεί. Ένα final κατηγό-

ρηµα έχει σταθερή τιµή.

garbage collector Συλλογέας σκουπιδιών.

HotJava Το πρώτο πρόγραµµα πλοήγησης που επέτρεψε την

συµπερίληψη Java applets σε ιστοσελίδες. Χαρα-

κτηρίζεται από το µικρό του µέγεθος (lightweight)

και το µεγάλο βαθµό παραµετροποίησης της διεπι-

φάνειας χρήστη.

HTML Συντοµογραφία του Hypertext Markup Language.

Χρησιµοποιείται για τη διαµόρφωση ιστοσελίδων, οι

οποίες είναι κατανοητές από προγράµµατα πλοήγησης.

identifier Aναγνωριστής.

implements Λέξη–κλειδί που χρησιµοποιείται στον ορισµό µιας

κλάσης για να δηλώσει το interface ή τα interfaces

που η κλάση υλοποιεί.

information hiding Aπόκρυψη πληροφορίας.

inheritance Kληρονοµικότητα.

instance Στιγµιότυπο.

instanceof Tελεστής της Java που επιστρέφει αληθές, αν το

αντικείµενο στην αριστερή πλευρά του είναι στιγ-

µιότυπο της κλάσης ή υλοποιεί το interface που

καθορίζεται από το δεξιό τελεστέο του.

instantiation Mορφή συσχέτισης µεταξύ κλάσεων που χρησιµο-

ποιούν γλώσσες όπως οι Ada, C++ και Eiffel και

υποστηρίζει όπως και η κληρονοµικότητα µια µορφή

γενίκευσης µε τελείως όµως διαφορετικό τρόπο.

interface Λέξη–κλειδί της Java που χρησιµοποιείται για τον

ορισµό της οµώνυµης κατασκευής.

interpreter Tο τελευταίο τµήµα του Java διερµηνευτή. ∆ιερµη-

νεύει τον κώδικα bytecode, εντολή προς εντολή, σε

2 4 1° § ø ™ ™ ∞ ƒ π √ ƒ ø ¡

Page 242: Γλώσσες Προγραμματισμού II

2 4 2 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

γλώσσα µηχανής, η οποία εκτελείται από την CPU

του µηχανήµατος.

Java API Συντοµογραφία του Java Applications Programming

Interface. Το σύνολο των µεταβλητών και µεθόδων

της βασικής βιβλιοθήκης της Java, το οποίο οι προ-

γραµµατιστές µπορούν να χρησιµοποιήσουν στις

εφαρµογές τους.

JDK Συντοµογραφία του Java Development Kit. Το πρώτο

περιβάλλον ανάπτυξης Java εφαρµογών. Αναπτύ-

χθηκε από την Sun.

late binding Όψιµη διασύνδεση.

link ∆εσµός.

maintainability Συντηρησιµότητα.

message Mήνυµα.

metaclass Mετα–κλάση.

method Mέθοδος.

method overloading Yπερφόρτωση µεθόδων.

Microsoft J++ Tο γραφικό περιβάλλον ανάπτυξης Java εφαρµογών

της Microsoft.

monitor Eλεγκτής.

multithreaded Πολυ–νηµατικός.

native Προσδιοριστής που εφαρµόζεται σε µεθόδους.

∆ηλώνει πως η µέθοδος είναι υλοποιηµένη κάπου

αλλού, συνήθως σε C ή σε άλλη γλώσσα άµεσα

εξαρτώµενη από το σύστηµα ανάπτυξης.

null Eιδική τιµή που φανερώνει πως µια µεταβλητή δεν

αναφέρεται σε κανένα αντικείµενο. ∆εν µπορεί να

µετατραπεί (cast) σε άλλους αριθµητικούς τύπους

ούτε να θεωρηθεί ίση µε 0 όπως στην C.

object Aντικείµενο.

object implementation Yλοποίηση αντικειµένου.

Page 243: Γλώσσες Προγραμματισμού II

object interface ∆ιεπαφή αντικειµένου.

Objective–C Γλώσσα αντικειµενοστρεφούς προγραµµατισµού.

Αποτελεί υπερσύνολο της ANSI C εισάγοντας πολ-

λές ιδέες από την Smalltalk. Ο µεταγλωττιστής της

έχει υλοποιηθεί σαν ένας προεπεξεργαστής της C.

package 1. Mια µονάδα κώδικα που περιλαµβάνει ένα σύνο-

λο από δηλώσεις κλάσεων.

2. Πρόταση της Java που τοποθετείται στην αρχή ενός

αρχείου πηγαίου κώδικα και προσδιορίζει το

package στο οποίο ανήκει ο κώδικας που ακολουθεί.

polymorphism Πολυµορφισµός.

private Προσδιοριστής ορατότητας της Java που µπορεί να

εφαρµοστεί σε µεθόδους και κατηγορήµατα και

περιορίζει την ορατότητα µόνο στο εσωτερικό της

κλάσης.

private protected Προσδιορίζει µεθόδους και µεταβλητές ορατές µόνο

µέσα στην κλάση και τις απογόνους της.

problem space classes Kλάσεις που αναπαριστούν έννοιες του προβλήµατος.

protected Προσδιοριστής ορατότητας της Java που µπορεί να

εφαρµοστεί σε µεθόδους και κατηγορήµατα και

περιορίζει την ορατότητα µέσα στην κλάση, στις

υποκλάσεις καθώς και σε όλες τις κλάσεις που περιέ-

χονται στο ίδιο πακέτο στο οποίο η κλάση ανήκει.

Υποκλάσεις σε διαφορετικά πακέτα µπορούν να

έχουν πρόσβαση σε protected µέλη δικά τους αλλά

και σε άλλα αντικείµενα που είναι υποκλάσεις αλλά

όχι σε µέλη στιγµιότυπων των υποκλάσεων.

public Προσδιοριστής ορατότητας της Java που µπορεί να

εφαρµοστεί σε κλάσεις, interfaces, µεθόδους και

κατηγορήµατα. Public κλάσεις ή interfaces είναι

ορατά από παντού. Public µέθοδοι και κατηγορήµα-

τα είναι ορατά όπου είναι ορατή και η κλάση τους.

reference types Tύποι αναφοράς.

2 4 3° § ø ™ ™ ∞ ƒ π √ ƒ ø ¡

Page 244: Γλώσσες Προγραμματισμού II

2 4 4 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

resumption model of Tεχνική χειρισµού εξαιρέσεων σύµφωνα µε την

exception handling οποία ο έλεγχος µετά τον χειρισµό της εξαίρεσης επι-

στρέφει στο σηµείο όπου η εξαίρεση δηµιουργήθηκε.

reusability Eπαναχρησιµοποίηση.

robustness Eυρωστία.

SDE Συντοµογραφία του Software Development

Environment.

semaphore Σηµατοφόρος.

server Aντικείµενο που ποτέ δεν ενεργεί σε άλλα αντικεί-

µενα, αλλά µόνο παρέχει εξυπηρετήσεις σε άλλα

αντικείµενα.

Simula Γλώσσα προγραµµατισµού που σχεδιάστηκε και ανα-

πτύχθηκε µεταξύ 1962 και 1967 από τους Ole–Johan

Dahl και Kristen Nygaard. Αν και αναπτύχθηκε αρχι-

κά για εξοµοίωση διακριτών συµβάντων, επεκτάθη-

κε στη συνέχεια και εξελίχθηκε σε γενικού σκοπού

γλώσσα προγραµµατισµού. Παρότι δεν χρησιµοποι-

ήθηκε ευρέως, ευνοεί την εφαρµογή των αρχών του

σύγχρονου προγραµµατισµού και εισήγαγε βασικές

έννοιες της αντικειµενοστρεφούς µορφής προγραµ-

µατισµού, όπως κλάση και αντικείµενο, κληρονοµι-

κότητα και δυναµική διασύνδεση.

Smalltalk Αντικειµενοστρεφής γλώσσα προγραµµατισµού. Σχε-

διάστηκε στο ερευνητικό κέντρο Palo Alto της Xerox

στις αρχές της δεκαετίας του 70. Οι βασικότερες

έννοιες της αποδίδονται στον Alan Kay που χρησι-

µοποίησε πολλά στοιχεία από τις Simula, LISP και

SketchPad. Παρά τις αρχικές προβλέψεις δεν κατά-

φερε να γίνει αρκετά δηµοφιλής, κύρια λόγω της

εµφάνισης της C++ και της Java.

solution space classes Kλάσεις που προστίθενται στο διάγραµµα κλάσεων

κατά τη φάση του σχεδιασµού και αναπαριστούν

έννοιες του χώρου επίλυσης.

static Προσδιοριστής της Java που εφαρµόζεται σε µεθό-

Page 245: Γλώσσες Προγραμματισμού II

δους (static or class method) και µεταβλητές (static

or class variable).

String Kλάση της βασικής βιβλιοθήκης της Java που ανα-

παριστά το αλφαριθµητικό µόνο ανάγνωσης.

StringBuffer Kλάση της βασικής βιβλιοθήκης της Java που ανα-

παριστά το αλφαριθµητικό ανάγνωσης–εγγραφής.

strongly–typed Mια γλώσσα χαρακτηρίζεται σαν strongly–typed,

όταν επιβάλλει σε όλες τις εκφράσεις, τις τιµές και

τα αντικείµενα να έχουν οπωσδήποτε κάποιον τύπο.

subclass Yποκλάση.

super Λέξη–κλειδί της Java που αναφέρεται στην ίδια τιµή

που αναφέρεται και το this, δηλαδή στο στιγµιότυπο

της κλάσης στο οποίο το µήνυµα απεστάλει. Η δια-

φορά είναι πως, ενώ το this είναι του τύπου της κλά-

σης στην οποία εµφανίζεται η µέθοδος που προσδιο-

ρίζει τη συµπεριφορά στο µήνυµα, το super είναι του

τύπου της πρόγονης κλάσης.

superclass Yπερκλάση.

synchronized Λέξη–κλειδί µε δύο σηµασίες. Σαν προσδιοριστής

εφαρµόζεται σε µέθοδο κλάσης ή στιγµιότυπου για

να δηλώσει πως η µέθοδος τροποποιεί την εσωτερι-

κή κατάσταση της κλάσης ή του στιγµιότυπου µε

τρόπο που δεν είναι thread–safe. Σαν πρόταση χρη-

σιµοποιείται για να προσδιορίσει ένα κρίσιµο τοµέα

του κώδικα.

termination model of Tεχνική χειρισµού εξαιρέσεων σύµφωνα µε την

exception handling οποία ο έλεγχος µετά το χειρισµό της εξαίρεσης

µεταβαίνει στον κώδικα που ακολουθεί τον κώδικα

σύλληψης και αντιµετώπισης της εξαίρεσης.

this Λέξη–κλειδί της Java. 1) Στο σώµα ενός δηµιουργού

α) αποτελεί την αναφορά για το στιγµιότυπο που

µόλις δηµιουργήθηκε, π.χ. this.x. β) Σαν πρώτη πρό-

ταση αναφέρεται σε έναν από τους άλλους δηµιουρ-

γούς της κλάσης π.χ. this(x,y);. 2) Στο σώµα άλλων

2 4 5° § ø ™ ™ ∞ ƒ π √ ƒ ø ¡

Page 246: Γλώσσες Προγραμματισμού II

2 4 6 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

µεθόδων µπορεί να χρησιµοποιηθεί για να τονίσει ότι

η µέθοδος αναφέρεται στα δεδοµένα του στιγµιότυ-

που που δέχτηκε το µήνυµα.

thread Nήµα.

throw Πρόταση που σηµατοδοτεί την εµφάνιση µιας εξαί-

ρεσης δηµιουργώντας ένα συγκεκριµένου τύπου

αντικείµενο εξαίρεσης.

Throwable Kλάση της βασικής βιβλιοθήκης της Java που ορίζει

τα γενικά χαρακτηριστικά των αντικειµένων εξαίρε-

σης που το σύστηµα µπορεί να εγείρει.

throws Λέξη–κλειδί της Java που χρησιµοποιείται στη δήλω-

ση µιας µεθόδου για να προσδιορίσει τις εξαιρέσεις

που η µέθοδος µπορεί να εγείρει.

try/catch/finally Πρόταση της Java που επιτρέπει τον χειρισµό εξαι-

ρέσεων.

UML Συντοµογραφία του Unified Modeling Language.

Γλώσσα που έγινε αποδεκτή το 1997 από τη βιοµη-

χανία παραγωγής λογισµικού σαν πρότυπη γραφική

γλώσσα για τεκµηρίωση και ανάπτυξη συστηµάτων

λογισµικού.

using Mορφή συσχέτισης µεταξύ κλάσεων που υποδηλώ-

νει ποια κλάση είναι πελάτης και ποια προµηθευτής

συγκεκριµένων εξυπηρετήσεων.

Visual Café Γραφικό περιβάλλον ανάπτυξης εφαρµογών Java της

Symantec.

web browser Πρόγραµµα πλοήγησης.

αναγνωριστής Tο χαρακτηριστικό του αντικειµένου που το διακρί-

νει µοναδιαία από τα άλλα αντικείµενα.

αντικείµενο Oντότητα φυσική ή ιδεατή που χαρακτηρίζεται από

κατάσταση (state), συµπεριφορά (behaviour) και ταυ-

τότητα (identity). Τα αντικείµενα λογισµικού προ-

σπαθούν να αναπαραστήσουν όσο το δυνατόν περισ-

σότερα από τα χαρακτηριστικά των αντικειµένων του

Page 247: Γλώσσες Προγραμματισμού II

πραγµατικού κόσµου στα οποία αντιστοιχούν.

ανώνυµη κλάση Kλάση που δηλώνεται χωρίς όνοµα.

ΑΠ Συντοµογραφία των Αντικειµενοστρεφής Προσέγγι-

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

απλή κληρονοµικότητα Mορφή κληρονοµικότητας που επιτρέπει την απόγο-

νο κλάση να κληρονοµήσει χαρακτηριστικά που ορί-

ζονται σε µια µόνο πρόγονο κλάση.

απόκρυψη πληροφορίας Bασική αρχή σχεδιασµού συστηµάτων σύµφωνα µε

την οποία κάθε οντότητα (σύστηµα, υποσύστηµα,

κλάση) δοµείται µε τρόπο που να αποκρύπτει λεπτο-

µέρειες που δεν αφορούν τον εξωτερικό κόσµο και

να κάνει ορατά µόνο τα απαραίτητα.

αφαιρετικότητα Aποτελεί µια απλοποιηµένη περιγραφή ή τεκµηρί-

(abstraction) ση που δίνει έµφαση σε ορισµένα χαρακτηριστικά

ενώ ταυτόχρονα αποσιωπεί άλλα.

αφηρηµένη κλάση Kλάση για την οποία δεν επιτρέπεται η δηµιουργία

(abstract class) στιγµιότυπων.

αφηρηµένη µέθοδος Mέθοδος για την οποία δεν ορίζεται υλοποίηση. Η

(abstract method) υλοποίηση της µεθόδου θα οριστεί από την κλάση

που θα την κληρονοµήσει.

βασική κλάση H κλάση που είναι στην κορυφή του δένδρου της

(base class) ιεραρχίας.

γενίκευση–ειδίκευση H σχέση µεταξύ µιας γενικής κλάσης και µιας κλά-

σης που είναι εξειδίκευση της.

δεσµός Mια σηµασιολογική σύνδεση µεταξύ ενός συνόλου

αντικειµένων διαµέσου της οποίας ένα αντικείµενο

επικοινωνεί µε ένα άλλο. Ο δεσµός είναι στιγµιότυ-

πο της συσχέτισης.

δηµιουργός Mέθοδος που έχει όνοµα ίδιο µε αυτό της κλάσης και

καλείται αυτόµατα κάθε φορά που ένα νέο στιγµιό-

τυπο της κλάσης δηµιουργείται.

διάγραµµα κλάσεων ∆ιάγραµµα που παριστά τις κλάσεις του συστήµατος

και τις µεταξύ τους συσχετίσεις.

2 4 7° § ø ™ ™ ∞ ƒ π √ ƒ ø ¡

Page 248: Γλώσσες Προγραμματισμού II

2 4 8 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

διασύνδεση H συσχέτιση ενός πράγµατος µε άλλο, όπως για

παράδειγµα η συσχέτιση ενός ονόµατος µε συγκε-

κριµένη µέθοδο, η συσχέτιση µιας τιµής σε µια µετα-

βλητή, κ.λπ.

διεπαφή αντικειµένου Tο τµήµα εκείνο του αντικειµένου που προσδιορίζει

τον τρόπο που αυτό παρέχει τις υπηρεσίες του.

δυναµική διασύνδεση H διασύνδεση που λαµβάνει χώρα στο χρόνο εκτέ-

λεσης σε αντίθεση µε αυτή που λαµβάνει χώρα στο

χρόνο µεταγλώττισης.

ελεγκτής Σύνθετη κατασκευή που χρησιµοποιείται για το συγ-

χρονισµό διεργασιών.

εµβέλεια (scope) Aποτελεί τη βάση της ενθυλάκωσης. Ορίζει µια

περιοχή του προγράµµατος µέσα στην οποία οι

κατασκευές της µεταβλητής, της µεθόδου, της κλά-

σης, του interface ή του πακέτου µπορούν να δηλω-

θούν και να χρησιµοποιηθούν. Έξω από την περιοχή

αυτή η κατασκευή δεν είναι ορατή και δεν υπάρχει.

ένθετη ή εσωτερική κλάση (nested or inner class)Κλάση που δηλώνεται µέσα

σε άλλη εµβέλεια, η οποία συνήθως είναι εµβέλεια

κλάσης αλλά µπορεί να είναι και τοπική εµβέλεια,

δηλαδή εµβέλεια σύνθετης πρότασης ή σώµατος

µεθόδου.

ενθυλάκωση H τεχνική που χρησιµοποιεί η ΑΠ για την απόκρυψη

της πληροφορίας. Ενθυλακώνεται η κατάσταση του

αντικείµενου και η υλοποίηση των µεθόδων του.

εξαίρεση Aπρόσµενο συµβάν στην εκτέλεση µιας διεργασίας.

επαναχρησιµοποίηση H ικανότητα των προϊόντων λογισµικού να επανα-

χρησιµοποιούνται, στο σύνολο τους ή εν µέρει, για

την ανάπτυξη νέων εφαρµογών.

επεκτασιµότητα O βαθµός ευκολίας µε τον οποίο τα προϊόντα λογι-

σµικού µπορούν να προσαρµοσθούν στις αλλαγές

των προδιαγραφών.

επικάλυψη µεταβλητής O ορισµός µεταβλητής σε απόγονο κλάση, µε όνοµα

Page 249: Γλώσσες Προγραμματισμού II

ίδιο µε αυτό µεταβλητής προγόνου κλάσης.

ευρωστία H ικανότητα των προϊόντων λογισµικού να λει-

τουργούν ακόµη και σε αντικανονικές (abnormal)

συνθήκες.

κλάση H αφαιρετική περιγραφή ενός συνόλου οµοειδών

αντικειµένων. Η υλοποίηση ενός τύπου (type).

κλάση µέλους Όρος που χρησιµοποιείται για να περιγράψει κλάση

(member class) που δηλώνεται µέσα σε άλλη κλάση.

κληρονοµικότητα O σηµαντικότερος µηχανισµός υλοποίησης της σχέ-

σης γενίκευσης–εξειδίκευσης. Υποστηρίζει επανα-

χρησιµοποίηση των χαρακτηριστικών της κλάσης.

κρίσιµος τοµέας Tµήµα κώδικα ενός αντικείµενου, που πρέπει να

(critical section) εκτελείται µε τρόπο που να αποκλείει την εκτέλεση

όλων των άλλων κρίσιµων τοµέων του ίδιου αντι-

κειµένου.

µέθοδος (method) Mονάδα κώδικα που προσδιορίζει τη συµπεριφορά

του αντικειµένου σε µήνυµα του εξωτερικού κόσµου.

Ο όρος χρησιµοποιείται πολλές φορές για να διακρί-

νει την προδιαγραφή µιας λειτουργίας (operation)

από τις πιθανόν πολλές υλοποιήσεις της, που ονοµά-

ζονται µέθοδοι.

µέθοδος κλάσης Μέθοδος που προσδιορίζει συµπεριφορά της κλάσης

(class method) και όχι των στιγµιότυπων της και για το λόγο αυτό

είναι ανεξάρτητη από την ύπαρξη ή µη στιγµιότυπων

της κλάσης.

µεταβλητή κλάσης Μεταβλητή που ανήκει στην κλάση και δεν αποτελεί

(class variable) µέρος της κατάστασης των στιγµιότυπων της. Μόνο

ένα αντίγραφο της κάθε µεταβλητής κλάσης δηµι-

ουργείται.

µετα–κλάση Kλάση της οποίας τα στιγµιότυπα είναι κλάσεις.

Περιέχει δεδοµένα και µεθόδους που προσδιορίζουν

κατάσταση και συµπεριφορά της κλάσης και όχι των

στιγµιότυπών της.

2 4 9° § ø ™ ™ ∞ ƒ π √ ƒ ø ¡

Page 250: Γλώσσες Προγραμματισμού II

2 5 0 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

µήνυµα Mια αίτηση που αποστέλλεται σε ένα αντικείµενο για

εκτέλεση συγκεκριµένης λειτουργίας. Περιλαµβάνει

το όνοµα της µεθόδου και προαιρετικά µια λίστα

παραµέτρων.

νήµα Mια ανεξάρτητη ακολουθία προτάσεων που εκτελεί-

ται ταυτόχρονα µε άλλες τέτοιες ακολουθίες µέσα σε

ένα πρόγραµµα.

ορθότητα Eίναι η ικανότητα των προϊόντων λογισµικού να εκτε-

λούν το έργο που τους ανατίθεται επακριβώς και όπως

ορίζεται από τις απαιτήσεις και τις προδιαγραφές.

όψιµη διασύνδεση H διασύνδεση που λαµβάνει χώρα στο χρόνο εκτέ-

λεσης του προγράµµατος.

πολλαπλή Mορφή κληρονοµικότητας που επιτρέπει την απόγονο

κληρονοµικότητα κλάση να κληρονοµήσει χαρακτηριστικά που ορίζονται

σε περισσότερες της µιας προγόνους κλάσεις.

πολυµορφισµός Έννοια σύµφωνα µε την οποία ένα όνοµα µπορεί να

αναφέρεται σε αντικείµενα που είναι στιγµιότυπα

διάφορων κλάσεων οι οποίες όµως οµαδοποιούνται

στα πλαίσια ενός δένδρου κληρονοµικότητας.

πολυ–νηµατικό H εφαρµογή που αποτελείται από πολλά νήµατα ή το

περιβάλλον που υποστηρίζει την εκτέλεση

πολυ–νηµατικών εφαρµογών.

πρόγραµµα πλοήγησης Eιδικό πρόγραµµα που υποστηρίζει την πρόσβαση

στην πληροφορία του διαδικτύου. Netscape’s

Communicator και Microsoft’s Internet Explorer

θεωρούνται τα πιο δηµοφιλή.

πρώιµη διασύνδεση H διασύνδεση που λαµβάνει χώρα στο χρόνο µετα-

γλώττισης του προγράµµατος.

σηµατοφόρος Πρωτογενές στοιχείο συγχρονισµού διεργασιών.

στιγµιότυπο Ένα από το σύνολο των αντικειµένων που αφαιρετι-

κά περιγράφει µια κλάση. Πολλές φορές χρησιµο-

ποιείται αντί αυτού ο όρος αντικείµενο.

συλλογέας σκουπιδιών Mηχανισµός της γλώσσας προγραµµατισµού ή του

Page 251: Γλώσσες Προγραμματισμού II

περιβάλλοντος ανάπτυξης, ο οποίος ασχολείται µε

τη συλλογή των αντικειµένων που πλέον δεν χρη-

σιµοποιούνται.

συµβατότητα H ευκολία µε την οποία προϊόντα λογισµικού µπο-

ρούν να συνδυαστούν µε άλλα προιόντα.

συµπερίληψη Mορφή συνάθροισης που αναπαριστά µη φυσική

µε αναφορά συµπερίληψη. Οι διάρκειες ζωής του όλου και του

(containment by reference) µέρους δεν έχουν ισχυρή εξάρτηση µεταξύ τους.

συµπερίληψη µε τιµή Mορφή συνάθροισης που αναπαριστά φυσική συµπε-

(containment by value) ρίληψη. Στην συµπερίληψη µε τιµή το µέρος δεν

υπάρχει ανεξάρτητα από το όλο.

συνάθροιση H σχέση που συνδέει ένα σύνθετο (composite) αντι-

κείµενο µε τα επί µέρους τµήµατα (components) από

τα οποία απαρτίζεται.

συντηρησιµότητα O βαθµός ευκολίας µε τον οποίο ένα προϊόν λογι-

σµικού µπορεί να προσαρµοσθεί (adapted), τελειο-

ποιηθεί (perfected) και διορθωθεί (corrected).

συσχέτιση Mια συγγένεια µεταξύ κλάσεων που περιγράφει ένα

σύνολο δεσµών.

τοπική κλάση (local class) Kλάση που δηλώνεται µέσα στην εµβέλεια µιας σύν-

θετης πρότασης ή µιας µεθόδου.

τύποι αναφοράς Έτσι ονοµάζονται στην Java τα αντικείµενα και οι

(reference types) πίνακες, γιατί η διαχείριση τους βασίζεται στην

έννοια της αναφοράς.

υλοποίηση αντικειµένου Tο τµήµα εκείνο του αντικείµενου που προσδιορίζει

την κατάσταση (µεταβλητές) και τη συµπεριφορά

του (σώµα µεθόδων).

υπερκάλυψη µεθόδου ∆υνατότητα που προσφέρουν αντικειµενοστρεφείς

γλώσσες σύµφωνα µε την οποία µια µέθοδος µιας

κλάσης επικαλύπτει µια µέθοδο προγόνου κλάσης της

που έχει το ίδιο όνοµα και τα ίδια ορίσµατα µε αυτήν.

υπερκλάση (superclass) Γενική κλάση που συνδέεται µε άλλη εξειδικευµένη

κλάση µε σχέση γενίκευσης–εξειδίκευσης.

2 5 1° § ø ™ ™ ∞ ƒ π √ ƒ ø ¡

Page 252: Γλώσσες Προγραμματισμού II

2 5 2 ° § ø ™ ™ ∂ ™ ¶ ƒ √ ° ƒ∞ ª ª ∞∆ π ™ ª √ À I I

υπερφόρτωση µεθόδων Tεχνική σύµφωνα µε την οποία η Java ,αλλά και

άλλες γλώσσες επιτρέπουν τη δήλωση περισσότερων

της µιας µεθόδων µε το ίδιο όνοµα, αρκεί αυτές να

διαφέρουν στον αριθµό ή στον τύπο των ορισµάτων

που δέχονται. Οι µέθοδοι αυτοί έχουν διαφορετικές

υλοποιήσεις και κατά συνέπεια η συµπεριφορά του

αντικείµενου σε ένα µήνυµα θα είναι ανάλογη του

αριθµού και του τύπου των παραµέτρων που συνο-

δεύουν το µήνυµα.

υποκλάση (subclass) Eξειδικευµένη κλάση που συνδέεται µε άλλη γενική

κλάση µε σχέση γενίκευσης–εξειδίκευσης.

χειρισµός εξαιρέσεων H διαδικασία της αναγνώρισης και διαχείρισης των

αντικανονικών (abnormal) καταστάσεων στη λει-

τουργία ενός συστήµατος.

Page 253: Γλώσσες Προγραμματισμού II
Page 254: Γλώσσες Προγραμματισμού II
Page 255: Γλώσσες Προγραμματισμού II
Page 256: Γλώσσες Προγραμματισμού II