This is an old revision of the document!
====== Η Κλάση ====== Στην [[:oop:introduction|Εισαγωγή στον Αντικειμενοστραφή Προγραμματισμό]] είδαμε την σχέση μεταξύ κλάσης και αντικειμένων. Εδώ θα δούμε πως ορίζουμε μία κλάση και θα ορίσουμε την πρώτη μας κλάση. Στην πιο απλή περίπτωση κάθε κλάση περιέχει τα εξής: - **δεδομένα ή πεδία (fields)** - **κατασκευαστές (constructors)** - **μεθόδους (methods)** Για τις ανάγκες του παρόντος κεφαλαίου θα ορίσουμε την κλάση **Rectangle** που απεικονίζει ένα ορθογώνιο παραλληλόγραμμο. Παρακάτω ορίζουμε την κλάση αυτή. <code java Rectangle.java> public class Rectangle { // the Rectangle class has 3 fields public int width; public int height; public int[] color;// (an array of 3 elements //to store information in RGB format) // the Rectangle class has one constructor public Rectangle(int setWidth, int setHeight, int[] setColor) { width = setWidth; height = setHeight; color = setColor; } // the Rectangel class has 4 methods public void setWidth(int newWidth ) { width = newWidth; } public void setHeight(int newHeight ) { height = newHeight; } public void setColor(int[] setColor) { color = setColor; } public String toString() { return "Width: "+width+", Height: "+height+", RGB: (0x"+Integer.toHexString(color[0]) +", 0x"+Integer.toHexString(color[1])+", 0x"+Integer.toHexString(color[0])+")"; } } </code> Παρατηρήστε ότι η παραπάνω κλάση αποτελείται από πεδία: * την μεταβλητή **width** που συμβολίζει το πλάτος του παραλληλογράμμου. * την μεταβλητή **height** που συμβολίζει το ύψος του παραλληλογράμμου. * την μεταβλητή **color** που είναι πίνακας τριών θέσεων και συμβολίζει το χρώμα του παραλληλογράμμου σε μορφή [[wp>RGB_color_model|RGB]]. και τις παρακάτω μεθόδους: <code java> public void setCadence(int newValue); public void setGear(int newValue); public void setGear(int newValue); public void applyBrake(int decrement); public void speedUp(int increment); </code> Προς το παρόν αγνοήστε τον προσδιοριστή **public** μπροστά από τα πεδία και τις μεθόδους, τον οποίο θα εξετάσουμε στην συνέχεια. ===== Ο κατασκευαστής της κλάσης ===== Εκτός από τις παραπάνω μεθόδους η κλάση διαθέτει μία "ειδική" μέθοδο που έχει το όνομα της κλάσης και δεν διαθέτει επιστρεφόμενο τύπο, όπως παρακάτω: <code java> public Bicycle(int startCadence, int startSpeed, int startGear); </code> Η "ειδική" αυτή μέθοδος αποτελεί τον κατασκευαστή της κλάσης. Ο κατασκευαστής της κλάσης έχει τις εξής δύο αρμοδιότητες: - Δεσμεύει την απαραίτητη μνήμη για την αποθήκευση του αντικειμένου που δημιουργείται. - Αρχικοποιεί τα δεδομένα ενός αντικειμένου, εφόσον διαθέτει τυπικές παραμέτρους και σώμα (σώμα μιας μεθόδου εννοούμε το τμήμα του κώδικα μέσα στις αγκύλες **{}** ). - Επιστρέφει ένα δείκτη στην αρχή της περιοχής που έχει δημιουργηθεί το νέο αντικείμενο της κλάσης. Υπό αυτή την έννοια, η μεταβλητή του κάθε αντικειμένου είναι ένας δείκτης (αναφορά) που δείχνει στο νέο αντικείμενο και όχι το αντικείμενο καθ' αυτό. <WRAP tip 80% center round> Η κάθε κλήση του κατασκευαστή της κλάσης δημιουργεί και επιστρέφει ένα αντικείμενο σε κάθε κλήση του. Κάθε κλάση έχει τουλάχιστον ένα κατασκευαστή (**//μπορεί να έχει και περισσότερους//**).__Εάν δεν έχει οριστεί κατασκευαστής σε μία κλάση__ o compiler ορίζει ένα κατασκευαστή χωρίς τυπικές παραμέτρους και χωρίς εντολές μέσα στο κυρίως σώμα. Για την παραπάνω κλάση Bicycle ο default κατασκευαστής θα ήταν o εξής: <code java> public Bicycle() { } </code> </WRAP> /* ====== Κληρονομικότητα Κλάσης ====== Η κλάση ''MountainBike'', η οποία ορίζεται ως υποκλάση της ''Bicycle'' θα μπορούσε να οριστεί ως εξής. <code java MountainBike.java> public class MountainBike extends Bicycle { // the MountainBike subclass has // one field public int seatHeight; // the MountainBike subclass has // one constructor public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) { super(startCadence, startSpeed, startGear); seatHeight = startHeight; } // the MountainBike subclass has // one method public void setHeight(int newValue) { seatHeight = newValue; } } </code> Η σχέση μεταξύ των κλάσεων ''Bike'' και ''MountainBike'' δίνεται μέσα από το keyword <color #B1B100/#FBFAF9>extends</color>. <code java> public class MountainBike extends Bicycle { .... } </code> H κλάση ''MountainBike'' κληρονομεί όλα τα πεδία και τις μεθόδους της κλάσης ''Bicycle'' και προσθέτει το πεδίο ''seartHeight'' και την μέθοδο <code java>public void setHeight(int newValue)</code> για τον ορισμό της τιμή του. Όταν μία κλάση κληρονομεί τα πεδία και τις μεθόδους της μητρικής κλάσης σημαίνει ότι μπορεί να τα χρησιμοποιήσει ως δικά της πεδία. Για να γίνει πιο αντιληπτό το παραπάνω, η κλάση ''MountainBike'' ισοδυναμεί με το παρακάτω. <code java> public class MountainBike { // the Bicycle class has // three fields public int cadence; public int gear; public int speed; // the MountainBike subclass has // one field public int seatHeight; // the MountainBike class has one constructor public MountainBike (int startHeight, int startCadence, int startSpeed, int startGear) { seatHeight = startHeight; gear = startGear; cadence = startCadence; speed = startSpeed; } // the Bicycle class has // four methods public void setCadence(int newValue) { cadence = newValue; } public void setGear(int newValue) { gear = newValue; } public void applyBrake(int decrement) { speed -= decrement; } public void speedUp(int increment) { speed += increment; } // the MountainBike subclass has // one method public void setHeight(int newValue) { seatHeight = newValue; } } </code> Συγκρίνοντας τους δύο παραπάνω ορισμούς της κλάσης ''MountainBike'' παρατηρούμε πόσο πιο κομψός είναι ο αρχικός ορισμός που χρησιμοποιεί την ιδιότητα της κληρονομικότητας. Επίσης, ο ορισμός αυτός μας δίνει την δυνατότητα να επαναχρησιμοποιήσουμε κώδικα που ήδη φτιάξαμε, αντί να επαναορίσουμε την κλάση εξ'αρχής. Επεκτείνοντας τον παραπάνω συλλογισμό θα μπορούσαμε να φτιάξουμε την κλάση ''BicycleWithGears'' από την κλάση ''Bicycle'' και στην συνέχεια να φτιάξουμε την κλάση ''MountainBikeWithGears'' από την κλάση ''BicycleWithGears'' δηλ. <code> Bicycle -> BicycleWithGears -> MountainBikeWithGears </code> Εάν ο παραπάνω συλλογισμός έχει ακόμη μεγαλύτερο βάθος, ο ορισμός και η συντήρηση κλάσεων χωρίς την χρήση της ιδιότητας της κληρονομικότητας γίνεται πολύ πολύπλοκη. ==== Ο κατασκευαστής της υποκλάσης ==== Επανερχόμενοι στο αρχικό παράδειγμα, παρατηρήστε των κατασκευαστή της κλάσης ''MountainBike''. <code java> // the MountainBike subclass has // one constructor public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) { super(startCadence, startSpeed, startGear); seatHeight = startHeight; } </code> Μέσω της κλήσης ''super(startCadence, startSpeed, startGear);'' καλείται ο κατασκευαστής της γονικής κλάσης (**SuperClass**) ''Bicycle''. Ο κατασκευαστής αυτός χρησιμοποιείται για να αρχικοποιήσει τις μεταβλητές που ορίζονται στην γονική κλάση. Η κλήση του κατασκευαστή της γονικής κλάσης είναι υποχρεωτική, με την έννοια ότι κατά την αρχικοποίηση του αντικειμένου θα πρέπει να αρχικοποιηθούν τα τμήματα του αντικειμένου που ανήκουν στην γονική κλάση. Έτσι ο compiler έχει τις εξής επιλογές: - Να κληθεί ο κατασκευαστής της γονικής κλάσης από τον προγραμματιστή, όπως κάνουμε στο παραπάνω παράδειγμα. - Να μην κληθεί κάποιος κατασκευαστής από τον προγραμματιστής. Σε αυτή την περίπτωση ο compiler αναζητά τον default κατασκευαστή της γονικής κλάσης, δηλαδή τον κατασκευαστή που δεν έχει ορίσματα. Αυτός μπορεί να υπάρχεί είτε γιατί έχει οριστεί ένας τέτοιος κατασκευαστής από τον προγραμματιστή, είτε διότι δεν έχει οριστεί κανένας κατασκευαστής για τη γονική κλάση, οπότε ο compiler αυτόματα φτιάχνει τον default κατασκευαστή. <WRAP tip> Αν δεν κληθεί κανένας κατασκευαστής από τον προγραμματιστή και ο compiler δεν βρει τον default κατασκευαστή της γονικής κλάσης τότε θα εμφανίσει ένα μήνυμα λάθους της μορφής. <code> error: no suitable constructor found for Bicycle (no arguments) </code> Συνηπώς, η αρχικοποίηση του αντικειμένου αποτελεί ευθύνη του προγραμματιστή ο οποίος θα πρέπει να φροντίσει είτε να καλέσει τον κατασκευαστή της γονικής κλάσης ή να βεβαιώσει ότι θα υπάρχει ο default κατασκευαστής. </WRAP> Τέλος, μία δήλωση της παρακάτω μορφής <code java> // the MountainBike subclass has // one constructor public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) { gear = startGear; cadence = startCadence; speed = startSpeed; seatHeight = startHeight; } </code> δηλαδή η αντικατάσταση του κώδικα που περιέχει ο κατασκευαστής της γονικής κλάσης μέσα στον κατασκευαστή της υποκλάσης **__δεν αναιρεί__** την ανάγκη να εκτελεστεί πρώτα ο default κατασκευαστής της γονικής κλάσης. */ |Προηγούμενο: [[:java:install| Εγκατάσταση Java]] | Επόμενο: [[:java:class_fields | Τα πεδία (δεδομενα) της κλάσης]]|