Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Εισαγωγή στον Προγ/μό Η/Υ Ενότητα 7: Εισαγωγή στα Αντικείμενα Διδάσκων: Μιχάλης Τίτσιας.

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "Εισαγωγή στον Προγ/μό Η/Υ Ενότητα 7: Εισαγωγή στα Αντικείμενα Διδάσκων: Μιχάλης Τίτσιας."— Μεταγράφημα παρουσίασης:

1 Εισαγωγή στον Προγ/μό Η/Υ Ενότητα 7: Εισαγωγή στα Αντικείμενα Διδάσκων: Μιχάλης Τίτσιας

2 Περιεχόμενα Τάξεις και Αντικείμενα Αφηρημένα δεδομένα (data abstraction) Κληρονομικότητα

3 Μηνύματα προς αντικείμενα X obj; obj αναφορά σε X

4 Μηνύματα προς αντικείμενα X obj; obj = new X(a, b, …); αντικείμενο Χ obj αναφορά σε X

5 Μηνύματα προς αντικείμενα X obj; obj = new X(a, b, …); αντικείμενο Χ obj αναφορά σε X

6 Μηνύματα προς αντικείμενα X obj; obj = new X(a, b, …); obj.μήνυμα(παρ1, παρ2,...); αντικείμενο Χ μήνυμα(παρ1, παρ2,...) obj αναφορά σε X

7 Μηνύματα προς αντικείμενα X obj; obj = new X(a, b, …); obj.μήνυμα(παρ1, παρ2,...); αντικείμενο Χ μήνυμα(παρ1, παρ2,...) τιμή obj αναφορά σε X

8 Αντικειμενοστραφής προγ/μός Με αντικείμενα επιτυγχάνουμε: – Εύκολη αλλαγή υλοποίησης – Επαναχρησιμοποίηση κώδικα – Εύκολη εισαγωγή νέας λειτουργικότητας Αντικειμενοστραφής προγραμματισμός: – Αφαίρεση μέσω δεδομένων (data abstraction) – Κληρονομικότητα – Πολυμορφισμός

9 Μηνύματα προς αντικείμενο τάξης String String s = new String(”hello”); s.equals(”world”); Είναι το ίδιο αλφαριθμητικό με το όρισμα; “hello” String equals(”world”) false

10 Μηνύματα προς αντικείμενο τάξης String s.length() Ποιό είναι το μήκος; “hello” String length() 5

11 Μηνύματα προς αντικείμενο τάξης String s.charAt(1) Ποιός χαρακτήρας βρίσκεται στη θέση 1; (1 η θέση = 0, 2 η θέση = 1, κτλ.) “hello” String charAt(1) ’e’

12 Μηνύματα προς αντικείμενο τάξης String s.indexOf(’l’) Θέση του χαρακτήρα ’l’ (1 η εμφάνιση από αριστερά); “hello” String indexOf(’l’) 2

13 Μηνύματα προς την τάξη String String.valueOf(93.103) Επιστρέφει την τιμή τύπου double (ή float ή int κτλ) ως (αναφορά σε) αντικείμενο String valueOf(93.103) String “93.103” String

14 Έμφαση στο δεδομένο Μέχρι τώρα η έμφαση δίνονταν στη συνάρτηση ως φορέα υπολογισμού. Στα αντικείμενα η έμφαση δίνεται στα δεδομένα.

15 Η τάξη RandomGenerator Πριν αρχίσετε να γράφετε τις δικές σας τάξεις, βοηθά να εξετάσετε πώς να χρησιμοποιήσετε τις τάξεις που έχουν αναπτυχθεί από άλλους. Το Κεφάλαιο 6 δείχνει την χρήση των υφιστάμενων τάξεων εισάγοντας την τάξη RandomGenerator, που καθιστά δυνατή την γραφή προγραμμάτων που προσομοιώνουν τυχαίες διαδικασίες, όπως η ρίψη ενός κέρματος ή ενός ζαριού. Τα προγράμματα που αφορούν τυχαίες διαδικασίες αυτού του είδους λέγονται μη- ντετερμινιστικά. Η μη- ντετερμινιστική συμπεριφορά είναι απαραίτητη σε πολλές εφαρμογές. Τα ηλεκτρονικά παιχνίδια θα έπαυαν να είναι διασκεδαστικά, αν συμπεριφέρονταν κάθε φορά με τον ίδιο ακριβώς τρόπο. Η μη- ντετερμινιστική συμπεριφορά έχει επίσης, πρακτικές χρήσεις σε προσομοιώσεις, στην ασφάλεια των υπολογιστών, και στην έρευνα αλγορίθμων.

16 Δημιουργία γεννήτριας τυχαίων αριθμών Το πρώτο βήμα στην σύνταξη ενός προγράμματος με τυχαιότητα είναι η δημιουργία ενός στιγμιότυπου της κλάσης RandomGenerator. Σύχνά, δημιουργείται ένα νέο στιγμιότυπο χρησιμοποιώντας τον τελεστη new, όπως έχετε ήδη δει. Από αυτή την εμπειρία, θα περίμενε κανείς η δημιουργία ενός αντικείμενου RandomGenerator να μοιάζει κάπως έτσι: RandomGenerator rgen = new RandomGenerator(); Για λόγους που θα δουμε αργοτερα η χρηση του new δεν κατάλληλη για την RandomGenerator επειδή θα πρέπει να υπάρχει μόνο μία γεννήτρια τυχαίων σε μια εφαρμογή. Έτσι πρεπει να ζητήσετε από την τάξη RandomGenerator ένα κοινό στιγμιότυπο που μπορεί να χρησιμοποιηθεί από όλες τις τάξεις στο πρόγραμμά σας private RandomGenerator rgen = RandomGenerator.getInstance(); Ο καλύτερος τρόπος δημιουργίας μιας RandomGenerator είναι η κλήση της μεθόδου getInstance, που επιστρέφει ένα κοινό στιγμιότυπο της γεννήτριας. Η τυποποιημένη μορφή της δήλωσης αυτής είναι: Η δήλωση αυτή εμφανίζεται συνήθως έξω από οποιαδήποτε μέθοδο και επομένως αποτελεί παράδειγμα μιας μεταβλητής στιγμιότυπου. Το private υποδεικνύει ότι η μεταβλητή μπορεί να χρησιμοποιηθεί από οποιαδήποτε μέθοδο εντός αυτής της τάξης, αλλά δεν είναι προσβάσιμη από αλλου. Όταν θέλετε μια τυχαία τιμή, στέλνετε ένα μήνυμα στο rgen, το οποίο στη συνέχεια επιστέφει το αποτέλεσμα.

17 Μέθοδοι παραγωγής τυχαίων τιμών Η τάξη RandomGenerator ορίζει τις ακόλουθες μεθόδους: int nextInt(int low, int high) Επιστρέφει ένα τυχαίο int μεταξύ των low και high, συμπεριλαμβανομένων. int nextInt(int n) Επιστρέφει ένα τυχαίο int μεταξύ των 0 και n - 1. double nextDouble(double low, double high) Επιστρέφει ένα τυχαίο double d στο διάστημα low ≤ d < high. double nextDouble() Επιστρέφει ένα τυχαίο double d στο διάστημα 0 ≤ d < 1. boolean nextBoolean() Επιστρέφει ένα τυχαίο boolean, που είναι true τις μισές φορές. boolean nextBoolean(double p) Επιστρέφει ένα τυχαίο boolean, που είναι true με πιθανότητα p, όπου 0 ≤ p ≤ 1. Color nextColor() Επιστρέφει ένα τυχαίο χρώμα.

18 Χρήση των Random μεθόδων Για να χρησιμοποιήσετε τις μεθόδους της προηγούμενης διαφάνειας, το μόνο που χρειάζεται είναι να καλέσετε τη μέθοδο αυτή χρησιμοποιώντας το rgen. Π.χ μπορείτε να εξομοιώσετε την ρίψη ενός ζαριού, καλώντας int die = rgen.nextInt(1, 6); Ομοίως, για την ρίψη ενός νομίσματος: String flip = rgen.nextBoolean() ? "Heads" : "Tails"; Σημειώστε ότι οι μέθοδοι nextInt, nextDouble, και nextBoolean υπάρχουν σε πολλές μορφές. Η Java μπορει να καταλάβει ποια εκδοχή θέλετε με βάση τον αριθμό και τον τύπο των ορισμάτων. Μέθοδοι που έχουν το ίδιο όνομα, αλλά διαφέρουν στα ορίσματα τους λέγονται υπερφορτωμένες.

19 Ασκήσεις: Δημιουργία τυχαίων τιμών Πώς θα λύνατε κάθε καθένα από τα παρακάτω προβλήματα; 1. Θέστε το total σαν το άθροισμα δυο ζαριών. int total = rgen.nextInt(2, 12); Η δήλωση αυτή κάνει το 2 τόσο πιθανό όσο το 7. int d1 = rgen.nextInt(1, 6); int d2 = rgen.nextInt(1, 6); int total = d1 + d2; 2. Στρίψτε ένα πειραγμένο νόμισμα που έρχεται κορώνα στο 60% των ρίψεων String flip = rgen.nextBoolean(0.6) ? "Heads" : "Tails"; 3. Αλλάξτε το χρώμα του rect σε κάποιο τυχαίο χρώμα. rect.setFillColor(rgen.nextColor());

20 Προσομοιώνοντας ένα παιχνίδι ζαριών public void run() { int total = rollTwoDice(); if (total == 7 || total == 11) { println("That's a natural. You win."); } else if (total == 2 || total == 3 || total == 12) { println("That's craps. You lose."); } else { int point = total; println("Your point is " + point + "."); while (true)... } Craps pointtotal 66396 while (true) { total = rollTwoDice(); if (total == point) { println("You made your point. You win."); break; } else if (total == 7) { println("That's a 7. You lose."); break; } d1d2total private int rollTwoDice() { int d1 = rgen.nextInt(1, 6); int d2 = rgen.nextInt(1, 6); int total = d1 + d2; println("Rolling dice: " + d1 + " + " + d2 + " = " + total); return total; } 46 Rolling dice: 4 + 2 = 6 2 Your point is 6. Rolling dice: 2 + 1 = 3 Rolling dice: 3 + 6 = 9 Rolling dice: 3 + 3 = 6 You made your point. You win. skip simulation 231 public void run() { int total = rollTwoDice(); if (total == 7 || total == 11) { println("That's a natural. You win."); } else if (total == 2 || total == 3 || total == 12) { println("That's craps. You lose."); } else { int point = total; println("Your point is " + point + "."); while (true)... } pointtotal 66

21 Πελάτες και Υλοποιήσεις Καθώς χρησιμοποιείτε τάξεις στη Java, είναι χρήσιμο να ξέρετε ότι υπάρχουν δύο αντίθετες οπτικές γωνίες που μπορείτε να έχετε για κάθε τάξη. Τις περισσότερες φορές, θα χρησιμοποιείτε μια έτοιμη τάξη, όπως στην περίπτωση της RandomGenerator. Σε τέτοιες περιπτώσεις, είστε πελάτης μιας τάξης. Όταν όμως γράφετε μια δική σας, κάνετε την υλοποίηση. Οι πελάτες και οι δημιουργοί βλέπουν τις τάξεις με διαφορετικούς τρόπους. Οι πελάτες πρέπει να γνωρίζουν ποιες μέθοδοι είναι διαθέσιμες σε μια τάξη και πώς να τις καλούν. Οι λεπτομέρειες για το πώς κάθε μέθοδος λειτουργεί δεν είναι σημαντικές. Οι δημιουργοί, από την άλλη πλευρά, ενδιαφέρονται πρωτίστως για αυτές τις λεπτομέρειες. Η υλοποίηση μιας τάξης πρέπει να κρύβει την πολυπλοκότητα από τους πελάτες της. Η τάξη RandomGenerator κρύβει ένα σημαντικό μέρος της πολυπλοκότητας της, όπως θα δείτε στις επόμενες διαφάνειες.

22 Πολυεπίπεδη αφαίρεση Η τάξη RandomGenerator στην πραγματικότιτα υλοποιείται ως υποτάξη μιας τάξης που ονομάζεται Random : Random RandomGenerator Μερικές από τις μεθόδους που καλείτε για την παραγωγή τυχαίων τιμών ορίζονται στην RandomGenerator, ενώ άλλες κληρονομούνται από την Random. Ως πελάτης, δεν χρειάζεται να ξέρετε ποια είναι ποια. Ιεραρχίες τάξεων που καθορίζουν μεθόδους σε διαφορετικά επίπεδα ονομάζονται πολυεπίπεδες αφαιρέσεις.

23 Πακέτα Java Κάθε τάξη στην Java αποτελεί μέρος ενός πακέτου, που είναι μια συλλογή σχετικών τάξεων ως συνεκτική μονάδα. Η RandomGenerator ορίζεται μέσα στο πακέτο acm.util, που είναι μέρος της βιβλιοθήκης ACM Java. Η τάξη Random είναι μέρος του πακέτου java.util, που οποία είναι μια συλλογή από τάξεις γενικής χρησιμότητας. Όταν αναφέρεστε απευθείας σε μια τάξη, θα πρέπει να εισαγάγετε το πακέτο στο οποίο αυτή υπάρχει. Π.χ., κάθε πρόγραμμα που χρησιμοποιεί την RandomGenerator πρέπει να περιλαμβάνει τη γραμμή import acm.util.*; Όταν χρησιμοποιείτε την RandomGenerator, δεν χρειάζεται να εισάγετε το java.util. Το γεγονός ότι η RandomGenerator έχει στηθεί πάνω στη Random είναι μέρος της πολυπλοκότητας που είναι κρυμμένο από τους πελάτες.

24 Προσομοιώνοντας την τυχαιότητα Η μη- ντετερμινιστική συμπεριφορά αποδεικνύεται δύσκολο να επιτευχθεί σε έναν υπολογιστή. Ένας υπολογιστής εκτελεί εντολές με έναν ακριβή, προβλέψιμο τρόπο. Αν σε ένα πρόγραμμα δώσετε τις ίδιες εισόδους, θα λάβετε τα ίδια αποτελέσματα, που δεν είναι αυτό που θέλετε σε ένα μη-ντετερμινιστικό πρόγραμμα Δεδομένου ότι ο πραγματικός μη-ντετερμινισμός είναι δύσκολο να επιτευχθεί στους υπολογιστές, τάξεις όπως η RandomGenerator προσομοιώνουν την τυχαιότητα με μια ντετερμινιστική διαδικασία που όμως ικανοποιεί τα ακόλουθα κριτήρια: 1.Οι τιμές που προκύπτουν από τη διαδικασία θα πρέπει να είναι δύσκολο να προβλεφθούν από ανθρώπους. 2.Οι τιμές πρέπει να μοιάζουν τυχαίες, με την έννοια ότι ικανοποιούν στατιστικούς ελέγχους για την τυχαιότητα. Επειδή η διαδικασία δεν είναι πραγματικά τυχαία, οι τιμές που παράγει η RandomGenerator λέγονται ψευδοτυχαίες.

25 Ψευδοτυχαίοι Αριθμοί Η RandomGenerator class χρησιμοποιεί μια μαθηματική διαδικασία για την δημιουργία μιας σειράς ακεραίων, που φαίνονται τυχαίοι. Ο κώδικας που υλοποιεί τη διαδικασία αυτή ονομάζεται γεννήτρια ψευδοτυχαίων αριθμών. Για να πάρετε ένα νέο ψευδοτυχαίο αριθμό, στέλνετε μήνυμα στη γεννήτρια ζητώντας τον επόμενο αριθμό της ακολουθίας. Ο καλύτερος τρόπος για να απεικονιστεί μια γεννήτρια ψευδοτυχαίων αριθμών είναι να την σκεφτείτε ως ένα μαύρο κουτί που παράγει μια αλληλουχία των τιμών, ακόμη και αν οι λεπτομέρειες για το πώς το κάνει είναι κρυμμένες: γεννήτρια ψευδοτυχαίων αριθμών Δώσε μου τον επόμενο ψευδοτυχαίο αριθμό Η γεννήτρια ανταποκρίνεται, επιστρέφοντας αυτή την τιμή. Η επανάληψη αυτών των βημάτων δημιουργεί μια νέα τιμή κάθε φορά. 1749940626892128508155629808

26 Ο σπόρος τυχαίων αριθμών Η γεννήτρια ψευδοτυχαίων αριθμών των Random και RandomGenerator παράγει τιμές εφαρμόζοντας μια συνάρτηση στο προηγούμενο αποτέλεσμα. Η αφετηρία για αυτή την ακολουθία των τιμών λέγεται σπόρος. Κατά τη διαδικασία εκκίνησης μιας εφαρμογής, η Java αρχικοποιει το σπόρο για τη γεννήτρια ψευδοτυχαίων αριθμών σε μία τιμή με βάση το ρολόι του συστήματος, το οποίο αλλάζει πολύ γρήγορα για την ανθρώπινη χρονική κλίμακα. Προγράμματα που θα ξεκινήσουν με λίγα χιλιοστά του δευτερολέπτου διαφορά θα πάρουν μια διαφορετική ακολουθία των τυχαίων τιμών. Οι υπολογιστές, όμως, τρέχουν πολύ πιο γρήγορα από ό, τι το εσωτερικό ρολόι. Αν δημιουργήσετε δυο στιγμιότυπα RandomGenerator σε ένα πρόγραμμα, είναι πιθανό ότι και τα δύο θα αρχικοποιηθούν με τον ίδιο σπόρο και έτσι θα παράγουν την ίδια ακολουθία τιμών. Αυτό εξηγεί γιατί είναι σημαντικό να δημιουργήσετε μόνο ένα στιγμιότυπο RandomGenerator σε ένα πρόγραμμα.

27 Εκσφαλμάτωση και τυχαία συμπεριφορά Παρότι η απρόβλεπτη συμπεριφορά είναι απαραίτητη σε κάποια προγράμματα, συχνά κάνει την εκσφαλμάτωση εξαιρετικά δύσκολη. Επειδή το πρόγραμμα εκτελείται με διαφορετικό τρόπο κάθε φορά, δεν υπάρχει κανένας τρόπος για να εξασφαλιστεί ότι ένα σφάλμα που προκύπτει την μια φορά θα συμβεί ξανά την επόμενη. Για να ξεπεράσετε αυτό το πρόβλημα, είναι συχνά χρήσιμο κατά τη φάση εντοπισμού σφαλμάτων να τρέχουμε τα προγράμματά μας ντετερμινιστικά. Για να γίνει αυτό, μπορείτε να χρησιμοποιήσετε τη μέθοδο setSeed έτσι: rgen.setSeed(1); Έτσι αρχικοποιούμε τον σπόρο ώστε η ακολουθία τυχαίων αριθμών θα αρχίζει πάντα από το ίδιο σημείο. Η τιμή 1 είναι αυθαίρετη, αλλαγή της θα αλλάξει την ακολουθία, αλλά η ακολουθία θα εξακολουθεί να είναι η ίδια σε κάθε τρέξιμο.

28 Το σύστημα τεκμηρίωσης javadoc Αντίθετα με προηγούμενες γλώσσες που εμφανίστηκαν πριν το διαδίκτυο, η Java έχει σχεδιαστεί για να λειτουργεί σε web-based περιβάλλον. Από το κεφάλαιο 1, ξέρετε ότι η Java δημιουργεί προγράμματα που τρέχουν στο διαδίκτυο, αλλά η σχέση της με αυτό δεν τελειώνει εκεί. Ένας από τους πιο σημαντικούς τρόπους με τους οποίους Java λειτουργεί μαζί με το διαδίκτυο είναι στο σχεδιασμό του συστήματος τεκμηρίωσης, που ονομάζεται javadoc. Η εφαρμογή javadoc διαβάζει αρχεία κώδικα και παράγει τεκμηρίωση για κάθε τάξη. Οι επόμενες διαφάνειες δείχνουν όλο και πιο λεπτομερείς εικόνες της τεκμηρίωσης javadoc της RandomGenerator Μπορείτε να δείτε την πλήρη τεκμηρίωση της βιβλιοθήκης ACM κάνοντας κλικ στον σύνδεσμο: http://jtf.acm.org/javadoc/student/

29 Δείγμα σελίδων javadoc StudentOverviewPackageCompleteTreeIndexHelp PREV CLASS NEXT CLASS FRAMES NO FRAMES DETAIL: FIELD | CONSTR | METHODSUMMARY: FIELD | CONSTR | METHOD acm.util Class RandomGenerator java.lang.Object | +--java.util.Random | +--acm.util.RandomGenerator public class RandomGenerator extends Random This class implements a simple random number generator that allows clients to generate pseudorandom integers, doubles, booleans, and colors. To use it, the first step is to declare an instance variable to hold the random generator as follows: private RandomGenerator rgen = RandomGenerator.getInstance(); By default, the RandomGenerator object is initialized to begin at an unpredictable point in a pseudorandom sequence. During debugging, it is often useful to set the internal seed for the random generator explicitly so that it always returns the same sequence. To do so, you need to invoke the setSeed method. The RandomGenerator object returned by getInstance is shared across all classes in an application. Using this shared instance of the generator is preferable to allocating new instances of RandomGenerator. If you create several random generators in succession, they will typically generate the same sequence of values.

30 Δείγμα σελίδων javadoc Constructor Summary Method Summary RandomGeneratorgetInstance() Returns a RandomGenerator instance that can be shared among several classes. booleannextBoolean(double p) Returns a random boolean value with the specified probability. ColornextColor() Returns a random opaque color whose components are chosen uniformly in the 0-255 range. doublenextDouble(double low, double high) Returns the next random real number in the specified range. intnextInt(int low, int high) Returns the next random integer in the specified range. Inherited Method Summary booleannextBoolean() Returns a random boolean that is true 50 percent of the time. doublenextDouble() Returns a random double d in the range 0 ≤ d < 1. intnextInt(int n) Returns a random int k in the range 0 ≤ k < n. voidsetSeed(long seed) Sets a new starting point for the random number generator. RandomGenerator() Creates a new random generator.

31 Δείγμα σελί δων javadoc Constructor Detail Method Detail public RandomGenerator() Creates a new random generator. Most clients will not use the constructor directly but will instead call getInstance to obtain a RandomGenerator object that is shared by all classes in the application. Usage: RandomGenerator rgen = new RandomGenerator(); public RandomGenerator() Returns a RandomGenerator instance that can be shared among several classes. Usage: RandomGenerator rgen = RandomGenerator.getInstance(); public boolean nextBoolean(double p) Returns a random boolean value with the specified probability. You can use this method to simulate an event that occurs with a particular probability. For example, you could simulate the result of tossing a coin like this: String coinFlip = rgen.nextBoolean(0.5) ? "HEADS" : "TAILS"; Usage: if (rgen.nextBoolean(p))... Returns:A shared RandomGenerator object Returns:The value true with probability p Parameter: p A value between 0 (impossible) and 1 (certain) indicating the probability

32 Γράφοντας Σχόλια στο javadoc Το σύστημα javadoc έχει σχεδιαστεί για να δημιουργεί αυτόματα ιστοσελίδες τεκμηρίωσης από τον πηγαίο κώδικα της Java. Για να γίνει αυτό με τα δικά σας προγράμματα, πρέπει να προσθέτετε ειδικά σχόλια στον κώδικά σας. Ένα σχόλιο javadoc ξεκινα με /** και εκτείνεται μέχρι το */ όπως και ένα απλό σχόλιο. Παρότι ο compiler αγνοεί αυτά τα σχόλια, η εφαρμογή javadoc τα διαβάζει για να βρει την απαραίτητη πληροφορία για την δημιουργία της τεκμηρίωσης Παρότι τα javadoc σχόλια μπορεί να αποτελούνται από απλό κείμενο, μπορούν να περιέχουν πληροφορίες μορφοποίησης σε HTML. Tα javadoc σχόλια συχνά περιέχουν ετικέτες @param και @result για να περιγράψουν παραμέτρους και αποτελέσματα.

33 Ορίζοντας τις δικιές σας τάξεις Η τυπική μορφή του ορισμού μιας τάξης στη Java είναι: public class name extends superclass { class body } Η φράση extends στην κεφαλίδα καθορίζει το όνομα της υπερτάξης. Αν παραλειφθεί, η νέα τάξη γίνεται άμεση υποτάξη του Object, που είναι η ρίζα της ιεραρχίας τάξεων της Java. Το σώμα μιας τάξης αποτελείται από μια συλλογή εντολών Java που γενικά ονομάζονται ε γγραφές. Οι πιο κοινές είναι οι κατασκευαστές, οι μέθοδοι, οι μεταβλητές, και οι σταθερές.

34 Ελέγχοντας την πρόσβαση στις εγγραφές Κάθε εγγραφή σε μια τάξη Java σημαίνεται με μία από τις ακόλουθες λέξεις- κλειδιά που ορίζουν ποιες τάξεις έχουν πρόσβαση σε αυτή : private protected (no keyword) public Όλες οι τάξεις στο πρόγραμμα έχουν πρόσβαση σε οποιαδήποτε τέτοια εγγραφή. Οι δημόσιες εγγραφές σε μια τάξη λέμε ότι εξάγονται. Εάν η λέξη-κλειδί λείπει, η εγγραφή είναι ορατή μόνο στις τάξεις του ίδιου πακέτου. Τέτοιες εγγραφές λέγονται package-private. Η πρόσβαση σε εγγραφές που εχουν δηλωθεί έτσι περιορίζεται στην ίδια την κλάση, κάνοντάς τες εντελώς αόρατες εκτός αυτής. Πρόσβαση περιορίζεται στην ίδια την τάξη και στις υποτάξεις της (πιθανόν σε διαφορετικά πακέτα ) ή σε τάξεις του ίδιου πακέτου. Εδώ χρησιμοποιούμε μόνο τις public και private. Όλες οι εγγραφές είναι private εκτός και αν υπάρχει σημαντικός λόγος.

35 Παράδειγμα: Μετρητής public class CounterTest extends Program { public void run() { Counter c1 = new Counter(); c1.increase(); println(c1.getValue()); Counter c2 = new Counter(); println(c2.getValue()); println(c1.getValue()); }

36 Ορισμός Τάξης Counter increase() getValue()

37 Ορισμός Τάξης Ορισμός τάξης = περιγραφή αντικειμένων της τάξης Counter value int increase() getValue() void increase() { value++;} void getValue() { return value; } Counter() {value=0;}

38 Ορισμός Τάξης public class Counter { private int value; // τρέχουσα τιμή public int getValue() { return value; } public void increase() { value++; } // Κατασκευαστής public Counter() { value = 0; } }

39 Ορισμός Τάξης public class Counter { private int value; // τρέχουσα τιμή public int getValue() { return value; } public void increase() { value++; } // Κατασκευαστής public Counter() { value = 0; } } Δεδομένα Μηνύματα Κατασκευαστής

40 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c1.increase() c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 0 Counter value int 0

41 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c1.increase() c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 0 Counter value int 0

42 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c1.increase() c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 0 Counter value int 0 increase()

43 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c1.increase() c2 αναφορά σε Counter Counter c1 αναφορά σε Counter int 1 Counter value int 0 increase()

44 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 0

45 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c2.increase() c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter int 1 increase()

46 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 1

47 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c2.increase() c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter int 2 increase()

48 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

49 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων x = c1.getValue(); c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2 getValue()

50 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων x = 1 c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2 getValue() 1

51 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

52 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων x = c2.getValue(); c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2 getValue()

53 Αντικείμενα Κάθε αντικείμενο της τάξης Counter, έχει το δικό του αντίγραφο των δεδομένων x = 2 c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2 getValue() 2

54 Παράδειγμα: Μετρητής Πρόσβαση σε μεταβλητή ενός αντικειμένου, χωρίς αποστολή μηνύματος; public class CounterTest extends Program { public void run() { Counter c1 = new Counter(); c1.value++; println(c1.value); Counter c2 = new Counter(); println(c2.value); }

55 Παράδειγμα: Μετρητής public class Counter { public int value; // τρέχουσα τιμή public int getValue() { return value; } public void increase() { value++; } // Κατασκευαστής public Counter() { value = 0; } } Αλλάξαμε το private int value σε public int value ώστε η τιμή να είναι ορατή εκτός της τάξης και να μπορούμε να γράφουμε πχ c1.value.

56 Πρόσβαση σε μεταβλητές αντικειμένων Πρέπει οι μεταβλητές να έχουν δηλωθεί public c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

57 Πρόσβαση σε μεταβλητές αντικειμένων Πρέπει οι μεταβλητές να έχουν δηλωθεί public c1.value c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

58 Πρόσβαση σε μεταβλητές αντικειμένων Πρέπει οι μεταβλητές να έχουν δηλωθεί public c1.value c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

59 Πρόσβαση σε μεταβλητές αντικειμένων Πρέπει οι μεταβλητές να έχουν δηλωθεί public c1.value c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

60 Πρόσβαση σε μεταβλητές αντικειμένων Πρέπει οι μεταβλητές να έχουν δηλωθεί public c2.value += 5; c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

61 Πρόσβαση σε μεταβλητές αντικειμένων Πρέπει οι μεταβλητές να έχουν δηλωθεί public c2.value += 5; c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

62 Πρόσβαση σε μεταβλητές αντικειμένων Πρέπει οι μεταβλητές να έχουν δηλωθεί public c2.value += 5; c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 2

63 Πρόσβαση σε μεταβλητές αντικειμένων Πρέπει οι μεταβλητές να έχουν δηλωθεί public c2.value += 5; c2 αναφορά σε Counter Counter c1 αναφορά σε Counter value int 1 Counter value int 7

64 Πολλαπλοί τρόποι αρχικοποίησης public void run() { Counter c1 = new Counter();//αρχική τιμή 0 Counter c2 = new Counter(3);//αρχική τιμή 3 println(c1.getValue()); println(c2.getValue()); }

65 Πολλαπλοί κατασκευαστές public class Counter { public int value; // τρέχουσα τιμή public int getValue() { return value; } public void increase() { value++; } // Κατασκευαστές public Counter(int start) { value = start; } public Counter() { value = 0; } }

66 Πολλαπλοί κατασκευαστές public class Counter { public int value; // τρέχουσα τιμή public int getValue() { return value; } public void increase() { value++; } // Κατασκευαστές public Counter(int start) { value = start; } public Counter() { this(0); }//Χρήση του άλλου κατ/στή }

67 Μέθοδοι που κληρονομούνται Σύμφωνα με το ορισμό «public class Counter» η τάξη Counter έχει ως υπέρ- τάξη (δηλ. επεκτείνει) την τάξη Object. Αυτό σημαίνει ότι κάποιες μέθοδοι κληρονομούνται από την υπέρ-τάξη. Πχ υπάρχει μια μέθοδος που έχει οριστεί στην Object που ονομάζεται toString που κατασκευάζει μια αλφαριθμητική σύνοψη της τιμής του αντικειμένου. Για να καλέσουμε αυτή τη μέθοδο, απλά γράφουμε το όνομα του αντικειμένου. Πχ println(c1) θα τυπώνει μια τιμή του αντικειμένου c1, η οποία για εμάς δε βγάζει κανένα νόημα διότι είναι η εσωτερική τιμή με την οποία η JAVA μπορεί να αναγνωρίζει αντικείμενα. Αν όμως συμπεριλάβουμε μια μέθοδο toString στον ορισμό της Counter τότε η νέα μέθοδος απόκτα προτεραιότητα σε σχέση με τον αρχικό ορισμό στην Object και αυτή είναι που θα εκτελεστεί. Στον αντικειμενοστρεφή προγραμματισμό αυτό ονομάζεται επικάλυψη (overriding).

68 Νέος ορισμός της μεθόδου toString public class Counter { public int value; // τρέχουσα τιμή public int getValue() { return value; } public void increase() { value++; } // Κατασκευαστές public Counter(int start) { value = start; } public Counter() { this(0); }//Χρήση του άλλου κατ/στη public String toString(){ return "Counter with current value " + value; }

69 Ρητοί αριθμοί Ως ένα πιο περίπλοκο παράδειγμα ορισμού μιας τάξης, η παράγραφος 6.4 ορίζει μια τάξη Rational για την αναπαράσταση ρητών αριθμών, που είναι απλά το πηλίκο δύο ακεραίων. Οι ρητοί αριθμοί μπορεί να είναι χρήσιμοι σε περιπτώσεις στις οποίες χρειάζεται ακριβής υπολογισμός με κλάσματα. Ακόμα κι αν χρησιμοποιείτε ένα double, ο δεκαδικός 0.1 αναπαρίσταται εσωτερικά ως προσέγγιση. Ο ρητός αριθμός 1 / 10 είναι ακριβής. Οι ρητοί αριθμοί μετέχουν στις συνήθεις αριθμητικές πράξεις a b + c d = ad + bc bd a b – c d = ad – bc bd a b x c d = ac a b c d =.. bd ad bc Πρόσθεση : Αφαίρεση : Πολλαπλασιασμός : Διαίρεση :

70 Ρητοί αριθμοί public class RatApp extends Program { public void run() { Rational r1 = new Rational(1, 2); Rational r2 = new Rational(4, 7); println(r1.toString()); println(r2.toString()); r1.add(r2); // Αύξηση του r1 κατά r2 println(r1.toString()); println(”Σύγκρινε με ”+(1.0/2+4.0/7)); }

71 Υλοποίηση της τάξης Rational Οι επόμενες πέντε διαφάνειες δείχνουν τον κώδικα της τάξης Rational μαζί με κάποιες σύντομες σημειώσεις. Όπως διαβάζετε τον κώδικα, τα ακόλουθα χαρακτηριστικά αξίζουν ιδιαίτερης προσοχής : –Οι κατασκευαστές είναι υπερφορτωμένοι. Καλώντας τον κατασκευαστή χωρίς όρισμα δημιουργείται ένα Rational με τιμή 0, καλώντας τον με ένα όρισμα, ένα Rational ίσο με αυτό τον ακέραιο, ενώ καλώντας τον με δύο ορίσματα δημιουργεί ένα κλάσμα. –Ο κατασκευαστής εξασφαλίζει ότι ο αριθμητής και ο παρονομαστής κάθε Rational είναι πάντα οι μικρότεροι δυνατοί. Επιπλέον, δεδομένου ότι οι τιμές αυτές δεν αλλάζουν ποτέ αφού δημιουργηθεί ένας Rational, αυτή η ιδιότητα θα παραμείνει σε ισχύ. –Οι μέθοδοι add, subtract, multiply, και divide είναι γραμμένες ώστε ο ένας τελεστέος είναι δέκτης (καθορίζονται από τη λέξη-κλειδί this ) και άλλος όρισμα. Έτσι, για να προσθέστε το r1 στο r2 θα γράφατε : r1.add(r2)

72 /** * The Rational class is used to represent rational numbers, which * are defined to be the quotient of two integers. */ public class Rational { /** Creates a new Rational initialized to zero. */ public Rational() { this(0); } /** * Creates a new Rational from the integer argument. * @param n The initial value */ public Rational(int n) { this(n, 1); } The Rational Class Αυτοί οι κατασκευαστές είναι υπερφορτωμένοι για να υπάρχουν πολλοί τρόποι για να δημιουργήσετε ένα Rational. Και οι δύο καλούν τον βασικό κατασκευαστή, χρησιμοποιώντας τη λέξη-κλειδί this. skip code page 1 of 5

73 /** * The Rational class is used to represent rational numbers, which * are defined to be the quotient of two integers. */ public class Rational { /** Creates a new Rational initialized to zero. */ public Rational() { this(0); } /** * Creates a new Rational from the integer argument. * @param n The initial value */ public Rational(int n) { this(n, 1); } /** * Creates a new Rational with the value x / y. * @param x The numerator of the rational number * @param y The denominator of the rational number */ public Rational(int x, int y) { int g = gcd(Math.abs(x), Math.abs(y)); num = x / g; den = Math.abs(y) / g; if (y < 0) num = -num; } /** * Adds the rational number r to this one and returns the sum. * @param r The rational number to be added * @return The sum of the current number and r */ public Rational add(Rational r) { return new Rational(this.num * r.den + r.num * this.den, this.den * r.den); } The Rational Class Ο βασικός κατασκευαστής δημιουργεί ένα νέο Rational από τον αριθμητή και τον παρονομαστή. Η κλήση του gcd εξασφαλίζει ότι το κλάσμα έχει τους μικρότερους όρος. Η μέθοδος add δημιουργεί ένα νέο αντικείμενο Rational χρησιμοποιώντας τον κανόνα πρόσθεσης. Οι δύο τιμές είναι οι this και r. skip code page 2 of 5

74 /** * Creates a new Rational with the value x / y. * @param x The numerator of the rational number * @param y The denominator of the rational number */ public Rational(int x, int y) { int g = gcd(Math.abs(x), Math.abs(y)); num = x / g; den = Math.abs(y) / g; if (y < 0) num = -num; } /** * Adds the rational number r to this one and returns the sum. * @param r The rational number to be added * @return The sum of the current number and r */ public Rational add(Rational r) { return new Rational(this.num * r.den + r.num * this.den, this.den * r.den); } /** * Subtracts the rational number r from this one. * @param r The rational number to be subtracted * @return The result of subtracting r from the current number */ public Rational subtract(Rational r) { return new Rational(this.num * r.den - r.num * this.den, this.den * r.den); } /** * Multiplies this number by the rational number r. * @param r The rational number used as a multiplier * @return The result of multiplying the current number by r */ public Rational multiply(Rational r) { return new Rational(this.num * r.num, this.den * r.den); } The Rational Class Αυτές οι μέθοδοι (μαζί με την divide στην επόμενη σελίδα) λειτουργούν όπως η add αλλά χρησιμοποιούν διαφορετικό τύπο. Σημειώστε ότι αυτές οι μέθοδοι έχουν πρόσβαση στις συνιστώσες του r. skip code page 3 of 5

75 /** * Subtracts the rational number r from this one. * @param r The rational number to be subtracted * @return The result of subtracting r from the current number */ public Rational subtract(Rational r) { return new Rational(this.num * r.den - r.num * this.den, this.den * r.den); } /** * Multiplies this number by the rational number r. * @param r The rational number used as a multiplier * @return The result of multiplying the current number by r */ public Rational multiply(Rational r) { return new Rational(this.num * r.num, this.den * r.den); } /** * Divides this number by the rational number r. * @param r The rational number used as a divisor * @return The result of dividing the current number by r */ public Rational divide(Rational r) { return new Rational(this.num * r.den, this.den * r.num); } /** * Creates a string representation of this rational number. * @return The string representation of this rational number */ public String toString() { if (den == 1) { return "" + num; } else { return num + "/" + den; } The Rational Class Αυτή η μέθοδος μετατρέπει τον αριθμό Rational σε μορφή συμβολοσειράς. Αν ο παρονομαστής είναι 1, ο αριθμός εμφανίζεται ως ακέραιος. skip code page 4 of 5

76 /** * Divides this number by the rational number r. * @param r The rational number used as a divisor * @return The result of dividing the current number by r */ public Rational divide(Rational r) { return new Rational(this.num * r.den, this.den * r.num); } /** * Creates a string representation of this rational number. * @return The string representation of this rational number */ public String toString() { if (den == 1) { return "" + num; } else { return num + "/" + den; } /** * Calculates the greatest common divisor using Euclid's algorithm. * @param x First integer * @param y Second integer * @return The greatest common divisor of x and y */ private int gcd(int x, int y) { int r = x % y; while (r != 0) { x = y; y = r; r = x % y; } return y; } /* Private instance variables */ private int num; /* The numerator of this Rational */ private int den; /* The denominator of this Rational */ } The Rational Class Η μέθοδος ΜΚΔ του Ευκλείδη έχει δηλωθεί private γιατί είναι μέρος της υλοποίησης της τάξης και δεν χρησιμοποιείται ποτέ έξω από αυτή. Ως συνήθως, οι μεταβλητές είναι private. skip code page 5 of 5

77 Προσομοίωση ρητών υπολογισμών Η επόμενη διαφάνεια παρουσιάζει όλα τα βήματα για τον υπολογισμό της πρόσθεσης τριών ρητών αριθμών. 1 2 1 3 1 6 ++ Με την χρήση του Rational, ο υπολογισμός είναι ακριβής. Αν γράψετε το ίδιο πρόγραμμα με την χρήση μεταβλητών τύπου double, το αποτέλεσμα θα είναι: RoundoffExample 1.0/2.0 + 1.0/3.0 + 1.0/6.0 = 0.999999999999999 Η προσομοίωση αντιμετωπίζει τις τιμές του Rational ως αφηρημένα αντικείμενα. Το κεφάλαιο 7 επαναλαμβάνει το παράδειγμα δείχνοντας τη δομή της μνήμης.

78 Προσθήκη τριών Rational τιμών csumba public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = a.add(b).add(c); println(a + " + " + b + " + " + c + " = " + sum); } TestRational 5 6 1 2 1 3 1 6 1 1 temporary result 1/2 + 1/3 + 1/6 = 1 skip simulation public Rational(int x, int y) { int g = gcd(Math.abs(x), Math.abs(y)); num = x / g; den = Math.abs(y) / g; if (y < 0) num = -num; } ygx this num den 12 1 1 2 public Rational(int x, int y) { int g = gcd(Math.abs(x), Math.abs(y)); num = x / g; den = Math.abs(y) / g; if (y < 0) num = -num; } ygx this num den 13 1 1 3 public Rational(int x, int y) { int g = gcd(Math.abs(x), Math.abs(y)); num = x / g; den = Math.abs(y) / g; if (y < 0) num = -num; } ygx this num den 16 1 1 6 public Rational add(Rational r) { return new Rational( this.num * r.den + r.num * this.den, this.den * r.den ); } this num den 1 2 r num den 1 3 6 5 public Rational(int x, int y) { int g = gcd(Math.abs(x), Math.abs(y)); num = x / g; den = Math.abs(y) / g; if (y < 0) num = -num; } ygx this num den 56 1 5 6 public Rational add(Rational r) { return new Rational( this.num * r.den + r.num * this.den, this.den * r.den ); } this num den 5 6 r num den 1 6 36 public Rational(int x, int y) { int g = gcd(Math.abs(x), Math.abs(y)); num = x / g; den = Math.abs(y) / g; if (y < 0) num = -num; } ygx this num den 36 1 1 csumba public void run() { Rational a = new Rational(1, 2); Rational b = new Rational(1, 3); Rational c = new Rational(1, 6); Rational sum = a.add(b).add(c); println(a + " + " + b + " + " + c + " = " + sum); } 1 2 1 3 1 6 1 1

79 Ρητοί αριθμοί με αντικείμενα Η run() δε γνωρίζει ότι χρησιμοποιούνται int στον αριθμητή/παρονομαστή των ρητών run Rational 1/2 Rational toString() add(r2) int n; int d;

80 Ρητοί αριθμοί με αντικείμενα Η run() δε γνωρίζει ότι χρησιμοποιούνται int στον αριθμητή/παρονομαστή των ρητών Εάν γίνει χρήση long αντί int στους ρητούς, δε θα πρέπει να αλλαχθεί και η run() run Rational 1/2 Rational toString() add(r2) long n; long d;

81 Αφηρημένα δεδομένα Η απόκρυψη λεπτομερειών των δεδομένων (π.χ., int, long) με την εισαγωγή νέων τύπων (όπως Rational) λέγεται αφαίρεση μέσω δεδομένων (data abstraction) Γενικότερη τεχνική από αντικείμενα. (Ισχύει και σε μη αντικειμενοστραφείς γλώσσες, αρκεί να επιτρέπεται ο ορισμός νέων τύπων δεδομένων από τον προγραμματιστή.)

82 Απόκρυψη τάξεων Μπορούμε να αποκρύψουμε ακόμη και τάξεις class Car { class Wheel { // Τάξη ορατή μόνο εντός της Car … // Βλέπει δεδομένα/μεθόδους της Car public String getCarPlate() { return plate; } } Wheel[] wheel_array; String plate = ”ONE1969”; … } «Φωλιασμένη» τάξη

83 Επεκτείνοντας υπάρχουσες τάξεις Τα παραδείγματα των προηγούμενων διαφανειών επεκτείνουν την τάξη Object. Τις περισσότερες φορές, όμως, θα θέλετε να επεκτείνετε μια υπάρχουσα τάξη για να δημιουργήσετε μια νέα, που να κληρονομεί τις περισσότερες από τις συμπεριφορές της από την υπερτάξη της, και να κάνει κάποιες μικρές επεκτάσεις ή τροποποιήσεις. Ας υποθέστε, ότι θελετε να ορίσετε μια νέα τάξη FilledRect που είναι παρόμοια με την GRect, με την διαφορά ότι είναι εξορισμού γεμισμένη αντί σκιαγραφημένη. Επιπλέον, θα θέλατε να μπορείτε να καθορίσετε προαιρετικά το χρώμα ως μέρος του κατασκευαστή. Π.χ. καλώντας την add(new FilledRect(10, 10, 100, 75, Color.RED)); πρέπει να δημιουργηθεί ένα γεμάτο κόκκινο ορθογώνιο 100x75 που να προστίθεται στον καμβά στο σημείο (10, 10). Ο κώδικας για το FilledRect εμφανίζεται στην επόμενη διαφάνεια.

84 Η τάξη FilledRect /** * This class is a GObject subclass that is almost identical * to GRect except that it starts out filled instead of outlined. */ public class FilledRect extends GRect { /** Creates a new FilledRect with the specified bounds. */ public FilledRect(double x, double y, double width, double height) { super(x, y, width, height); setFilled(true); } /** Creates a new FilledRect with the specified bounds and color. */ public FilledRect(double x, double y, double width, double height, Color color) { this(x, y, width, height); setColor(color); } Αυτή η σύνταξη καλεί τον κατασκευαστή της υπερτάξης. Η σύνταξη αυτή καλεί ένα άλλο κατασκευαστή σε αυτή την τάξη.

85 Κανόνες για κληρονομούμενους κατασκευαστές Κάθε φορά που δημιουργείτε ένα αντικείμενο μιας εκτεταμένης τάξης, η Java πρέπει να καλέσει κάποιο κατασκευαστή για την υπερτάξη ώστε να εξασφαλίσει ότι η δομή της είναι σωστά αρχικοποιημένη. Εάν η υπερτάξη δεν ορίζει ρητά κατασκευαστές, η Java παρέχει αυτόματα ένα απλό κατασκευαστή με ένα άδειο σώμα. Η Java συνεπώς, καλεί έναν κατασκευαστή υπερτάξης με έναν από τους παρακάτω τρόπους : –Τάξεις που αρχίζουν με ρητή κλήση του this καλούν έναν από τους άλλους κατασκευαστές αυτής της τάξης, αναθέτοντας την ευθύνη στον εν λόγω κατασκευαστή να διασφαλίσει ότι θα κληθεί ο κατασκευαστής υπερτάξης. –Τάξεις που αρχίζουν με κλήση του super επικαλούνται τον κατασκευαστή της υπερτάξης που να ταιριάζει με την λίστα ορισμάτων που παρέχεται. –Τάξεις που αρχίζουν χωρίς κλήση στο super ή το this καλούν τον προεπιλεγμένο κατασκευαστή της υπερτάξης χωρίς παραμέτρους.

86 Κανόνες για κληρονομούμενους κατασκευαστές Έστω ότι έχουμε της ακόλουθη ιεραρχία τάξεων Αν έχουμε την εντολή Mercedes m1 = new Mecredes();, τότε η Java: –Καλεί τον κατασκευαστή της Mercedes –O κατασκευαστής της Mercedes καλεί τον κατασκευαστή της Car –O κατασκευαστής της Car καλεί τον κατασκευαστή της Vehicle –O κατασκευαστής της Vehicle καλεί τον κατασκευαστή της Object –Ο κατασκευαστής της Object εκτελεί τις εντολές του και έπειτα επιστρέφουμε στον κατασκευαστή της Vehicle –O κατασκευαστής της Vehicle εκτελεί τις υπόλοιπες εντολές του και επιστρέφει στον κατασκευαστή της Car –…. και συνεχίζουμε ώσπου να κατασκευαστεί το αντικείμενο m1 – public class Vehicle { … } public class Car extends Vehicle { … } public class Mercedes extends Car { … }

87 Κανόνες για κληρονομούμενες μεθόδους Όταν μία τάξη επεκτείνει μια άλλη, η υποτάξη μπορεί να παρακάμπτει τους ορισμούς μεθόδων της υπερτάξης. Όταν καλείται η εν λόγω μέθοδος, η Java επιλέγει τη νέα έκδοση της μεθόδου που ορίζεται στην εν λόγω τάξη και όχι την αρχική έκδοση της που περιέχεται στην υπερτάξη. Η απόφαση για το ποια έκδοση μιας μεθόδου χρησιμοποιηθεί γίνεται πάντα με βάση τι είναι το αντικείμενο στην πραγματικότητα, και όχι σε αυτό που τυγχάνει να έχει δηλωθεί σε εκείνο το σημείο στον κώδικα. Αν χρειαστεί να καλέστε την αρχική έκδοση της μεθόδου, ​​μπορείτε να το κάνετε χρησιμοποιώντας τη λέξη- κλειδί super ως δέκτη. Π.χ. αν χρειάζεται να καλέσετε την αρχική έκδοση μιας μεθόδου init όπως ορίζεται στην υπερτάξη, μπορείτε να καλέσετε super.init();

88 Διάβασμα για το σπίτι Κεφάλαιο 6 από «Η Τέχνη και Επιστήμη της JAVA: Μια εισαγωγή στην Επιστήμη των Υεπολογιστών», E. Roberts Κεφάλαιο 5 και 6 του βιβλίου «Εισαγωγή στην JAVA», Γιώργος Λιακέας.


Κατέβασμα ppt "Εισαγωγή στον Προγ/μό Η/Υ Ενότητα 7: Εισαγωγή στα Αντικείμενα Διδάσκων: Μιχάλης Τίτσιας."

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google