ΠΛΗΡΟΦΟΡΙΚΗ ΙΙ (JAVA) 11/3/2008 Κατασκευαστές (Constructors) Ειδικός τύπος μεθόδων, οι οποίες: - είναι public και έχουν το ίδιο όνομα με αυτό της κλάσης - χρησιμοποιούνται για να αρχικοποιήσουν κάποιες μεταβλητές των αντικειμένων που δημιουργούν - καλούνται αυτόματα όταν αρχικοποιούμε ένα αντικείμενο κάποιας κλάσης - δεν επιστρέφουν κάποια τιμή Σε μία κλάση με το όνομα ClassName: public class ClassName private int a; private String b; // default constructor: public ClassName() // another constructor: public ClassName(int x, String s) a = x; b = s; // other statements, methods, etc. Κάθε κλάση περιέχει (αυτόματα από την Java) τον default constructor, παρόλο που δεν φαίνεται στον κώδικά της. Ο default constructor παύει να δίνεται αυτόματα από τη στιγμή που δημιουργηθεί έστω και ένας constructor από τον προγραμματιστή. Εάν θέλουμε να μπορούμε να φτιάχνουμε αντικείμενα της κλάσης με τον απλό τρόπο (χωρίς παραμέτρους εισόδου για αυτόματη αρχικοποίηση μεταβλητών) θα πρέπει να προσθέσουμε στον κώδικα της κλάσης τον default constructor. 1
Παράδειγμα κατασκευαστών στην κλάση Circle: public class Circle private double x, y; // συντεταγμένες κέντρου private double r; // ακτίνα // μέθοδος για υπολογισμό εμβαδού κύκλου public double area() return Math.PI*Math.pow(r,2); // μέθοδος για υπολογισμό περιφέρειας κύκλου public double circumf() return 2*Math.PI*r; Οι μεταβλητές x, y και r είναι private. Ένας τρόπος για να τους δώσουμε τιμές θα ήταν η ύπαρξη αντίστοιχων modifier (τροποποιητικών) μεθόδων στην κλάση Circle. Επειδή όμως κάθε αντικείμενο («κύκλος») που θα δημιουργούμε αναγκαστικά θα πρέπει να έχει τουλάχιστον κάποια δεδομένη ακτίνα, μπορούμε να αυτοματοποιήσουμε την απόδοση τιμών σε (κάποιες από) αυτές τις μεταβλητές, με τη δημιουργία κάποιων κατασκευαστών: public Circle(double a, double b, double c) x = a; y = b; r = c; public Circle(double r) x = 0; y = 0; this.r = r; public Circle() x = 0; y = 0; r = 1; // το this. αναφέρεται στη // μεταβλητή της κλάσης [Οι constructors αυτοί τοποθετούνται φυσικά μέσα στην κλάση Circle, μετά τις δηλώσεις των μεταβλητών και συνήθως πριν τις μεθόδους της κλάσης] 2
Ο πρώτος constructor αρχικοποιεί όλες τις μεταβλητές, ο δεύτερος αρχικοποιεί μόνο την ακτίνα (θέτοντας συγχρόνως τη θέση του κύκλου στο σημείο (0,0)), ενώ ο τρίτος είναι παραλλαγή του default constructor και δημιουργεί «μοναδιαίους κύκλους» (αντικείμενα με r = 1). Έτσι, μπορούμε να έχουμε τις εξής δηλώσεις για τη δημιουργία αντικειμένων της κλάσης Circle (μέσα σε κάποια άλλη κλάση φυσικά): Circle c1 = new Circle(2.5, 3.5, 6); (δημιουργεί «κύκλο» με κέντρο στο (2.5,3.5) και ακτίνα 6) Circle c2 = new Circle(4.3); (δημιουργεί «κύκλο» με κέντρο στο (0,0) και ακτίνα 4.3) Circle c3 = new Circle(); (δημιουργεί μοναδιαίο «κύκλο» στο (0,0)) Circle c4 = new Circle(1.3, 4.5); ΛΑΘΟΣ! Δεν έχουμε φτιάξει constructor που να δέχεται δύο παραμέτρους... ΕΛΕΓΧΟΣ ΡΟΗΣ ΠΡΟΓΡΑΜΜΑΤΟΣ Ι. Ελεγκτές συνθηκών ή περιπτώσεων: i) if/else ii) switch II. Επαναληπτικές διαδικασίες: iii) for iv) while και do/while - if/else: if (συνθήκη) if (συνθήκη) // if true else else if(συνθήκη) // if false else if(συνθήκη) else 3
Η συνθήκη είναι πάντα μια boolean έκφραση (λογική σχέση ή boolean μεταβλητή). Το if/else μπορεί να γραφτεί σε συνοπτική μορφή (σε περιπτώσεις απόδοσης τιμής): if (x > y) max = x; else max = (x > y)? x : y; max = y; π.χ. if (test) dothis(); dothat(); Σε αυτό το παράδειγμα δεν υπάρχει else. Επομένως μόνο το dothis() «ανήκει» στο if και εκτελείται μόνο εάν το test είναι true. Το dothat() εκτελείται ούτως ή άλλως, αφού βρίσκεται μετά το if. if (test) dothis(); else dothat(); Σε αυτό το παράδειγμα το dothat() «ανήκει» στην else περίπτωση του if, άρα εκτελείται μόνο εάν το test είναι false. - switch: switch (varname) case value1: break; // ή return case value2: break; case value3: break; 4
default: Η μεταβλητή VarName είναι είτε ακέραια, είτε τύπου boolean, είτε τύπου char. Το switch «στέλνει» τη ροή του κώδικα στο ισχύον case. Αν δεν υπάρχει κάποιο break (ή return) στο τέλος ενός case, τότε η ροή του κώδικα συνεχίζει στο επόμενο case! Δηλαδή, κάνει έλεγχο των case μέχρι να βρει αυτό που ισχύει και από εκεί και πέρα δεν ελέγχει εάν τα υπόλοιπα ισχύουν ή όχι, αλλά απλά εκτελεί τον κώδικα μέχρι να βρει κάποιο break ώστε να βγει από το switch. - for: for (int counter=initval; counter<=finalval; counter++) Σειρά εκτέλεσης εντολών: i) int counter = initval; ii) έλεγχος counter<=finalval? iii) iv) counter++ v) έλεγχος counter<=finalval? vi) κτλ. Συνήθως ο μετρητής (counter) ορίζεται τοπικά, στο πρώτο μέρος της παρένθεσης του forloop, δηλαδή είναι μια τοπική μεταβλητή (με εμβέλεια (scope) μόνο το for-loop). Παράδειγμα: for (int i=0; i<5; i++) Τυπώνει: 0 1 System.out.println(i); 2 3 4 - while: - do/while while(συνθήκη) do while(συνθήκη); 5
Η συνθήκη είναι ένα boolean expression (άρα: true ή false) Κάνουν επανάληψη των statements καθ όσον η συνθήκη είναι αληθής. Η διαφορά μεταξύ τους είναι ότι το do/while θα εκτελέσει τα statements τουλάχιστον μία φορά, ανεξάρτητα με το αν είναι true ή όχι η συνθήκη, αφού την ελέγχει στο τέλος του loop, ενώ η while δεν μπαίνει καθόλου στο loop αν αρχικά η συνθήκη είναι false. ΠΕΡΙΣΣΟΤΕΡΑ ΓΙΑ ΤΟΝ ΕΛΕΓΧΟ ΡΟΗΣ ΣΤΙΣ ΣΗΜΕΙΩΣΕΙΣ ΤΗΣ ΠΛΗΡΟΦΟΡΙΚΗΣ Ι Παράδειγμα: public class MyClass private int n=4;... public void methodname() for (int n=0; n<4; ++n) do while (n<3) System.out.println( n = + n++); n+=1; while (n<10); // end for System.out.println( Final value of n = + n); // end method // end class Η κλήση της μεθόδου methodname εκτυπώνει τα εξής: n = 0 n = 1 n = 2 Final value of n = 4 (στο τελευταίο System.out.println η τιμή του n είναι 4 διότι πρόκειται για τη μεταβλητή n της κλάσης και όχι για την τοπική μεταβλητή n του for, η οποία δεν υφίσταται σε αυτό το σημείο). 6
Εισαγωγή δεδομένων από το πληκτρολόγιο με χρήση της Scanner i) Εισαγωγή στο πρόγραμμα της «βιβλιοθήκης» util, με την εντολή: import java.util.*; στην αρχή της κλάσης, πριν την επικεφαλίδα της. ii) Δημιουργία αντικειμένου της κλάσης Scanner: Scanner input = new Scanner(System.in); (το αντικείμενο ονομάστηκε input, αλλά θα μπορούσε να έχει οποιοδήποτε άλλο όνομα) iii) Κλήση κατάλληλης μεθόδου της Scanner, π.χ.: int a = input.nextint(); double b = input.nextdouble(); String c = input.nextline(); (παραδείγματα στο επόμενο μάθημα) 7