This is an old revision of the document!
Κεντρικό στοιχείο του Αντικειμενοστραφούς Προγραμματισμού είναι η χρήση αντικειμένων. Τα αντικείμενα στον αντικειμενοστραφή προγραμματισμό τείνουν να προσομοιάσουν ευρύτερες έννοιες που υφίστανται στον πραγματικό κόσμο. Παραδείγματα αντικειμένων μπορεί να είναι το αυτοκίνητο, το ποδήλατο, η τηλεόραση, ο υπολογιστής κλπ.
Τα “αντικείμενα” στον πραγματικό κόσμο έχουν δύο βασικά χαρακτηριστικά:
Σε αναλογία των παραπάνω, τα αντικείμενα στον αντικειμενοστραφή προγραμματισμό διαθέτουν:
Ο αντικειμενοστραφής προγραμματισμός αποτελεί εξέλιξη του διαδικαστικού προγραμματισμού (που υποστηρίζεται από την γλώσσα C). Με την έννοια αυτή τα βασικά εργαλεία του διαδικαστικού προγραμματισμού, οι μεταβλητές και οι συναρτήσεις τα συναντούμε και στον αντικειμενοστραφή προγραμματισμό. Οι γλώσσες αντικειμενοστραφή προγραμματισμού όμως παρέχουν και άλλα πιο σύνθετα εργαλεία που επιτρέπουν την οργάνωση του κώδικα με πιο δομημένο τρόπο.
Τα παραδείγματα αντικειμένων που αναφέρθηκαν παραπάνω μπορεί κάποιος να τα δει με δύο διαφορετικούς τρόπους: α) το σχέδιο του κάθε αντικειμένου και β) το αντικείμενο αυτό καθ' αυτό.
Για παράδειγμα, όταν παράγεται ένα αυτοκίνητο, αυτό αποτελεί υλοποίηση του βασικού σχεδίου του αυτοκινήτου, έτσι όπως αυτό υλοποιείται από το εργοστάσιο κατασκευής. Μέρος του σχεδίου είναι η ύπαρξη κάποιων παραμέτρων όπως το χρώμα ή το επίπεδο του εξοπλισμού.
Τον ρόλο του σχεδίου με την έννοια που αναφέρεται παραπάνω τον παίζει η κλάση. Η κλάση αποτελεί το σχέδιο με βάση το οποίο αντικείμενα του συγκεκριμένου τύπου (της συγκεκριμένης κλάσης) υλοποιούνται σε ένα πρόγραμμα.
Όλα τα αντικείμενα της ίδιας κλάσης διέπονται από τις ίδιες εσωτερικές μεταβλητές (που αποτελούν τα δεδομένα ή πεδία της κλάσης) και από τις ίδιες συμπεριφορές (μεθόδους ή συναρτήσεις). Τα αντικείμενα της ίδιας κλάσης μπορεί να διαφέρουν ως προς τις τιμές των εσωτερικών τους μεταβλητών.
Στον πραγματικό κόσμο μπορούμε να έχουμε διαφορετικές υλοποιήσεις ενός σχεδίου, διαφοροποιώντας κάποιες αρχικές παραμέτρους στο σχέδιο αυτό. Χαρακτηριστικό παράδειγμα από τον πραγματικό κόσμο αποτελεί το αυτοκίνητο. Για ένα συγκεκριμένο μοντέλο αυτοκινήτου μπορούμε να έχουμε διαφοροποίηση στο επίπεδο του εξοπλισμού ή στο χρώμα. Για κάθε μοντέλο παράγονται χιλιάδες αυτοκίνητα, όπου το κάθε ένα έχει συγκεκριμένα χαρακτηριστικά όπως ο κυβισμός, το χρώμα και το επίπεδο του εξοπλισμού.
Ανάλογα, στον αντικειμενοστραφή προγραμματισμό, οποιαδήποτε κλάση μπορεί να δώσει πολλαπλά διαφορετικά αντικείμενα. Η κλάση για τα αντικείμενα είναι το βασικό σχέδιο μέσω του οποίου δημιουργούνται. Τα αντικείμενα που παράγει μία κλάση μπορεί να διαφοροποιούνται ως προς τα χαρακτηριστικά τους. Σκεφτείτε το ανάλογο ενός μοντέλου-τύπου αυτοκινήτου, όπου όλα τα αυτοκίνητα που παράγονται υπακούουν στο ίδιο βασικό σχέδιο, αλλά διαφοροποιούνται ως προς τα χαρακτηριστικά που αναφέραμε παραπάνω.
Κάθε αντικείμενο υλοποιείται από μία μέθοδο που καλείται κατασκευαστής (constructor). Ο κατασκευαστής της κλάσης υλοποιεί το κάθε αντικείμενο με βάση το σχέδιο της κλάσης και μπορεί να κληθεί για διαφορετικά αντικείμενα με διαφορετικές παραμέτρους, οδηγώντας τελικά σε διαφοροποιημένα αντικείμενα ως προς τα χαρακτηριστικά τους.
Μία κλάση έχει τουλάχιστον ένα κατασκευαστή. Οι κατασκευαστές είναι μέθοδοι (συναρτήσεις) που κάνουν τα εξής:
Κάθε κλάση περιέχει κατά βάση τρία τις παρακάτω βασικές κατηγορίες πληροφορίας
Κάθε κλάση στον αντικειμενοστραφή προγραμματισμό δηλώνει ένα τύπο δεδομένων. Με την έννοια αυτή τα πεδία της κλάσης μπορεί να είναι του τύπου μιας άλλης κλάσης, δηλαδή μία κλάση μπορεί να περιέχει πολλαπλά πεδία που να ανήκουν σε άλλες κλάσεις (ή και στην ίδια κλάση σε κάποιες περιπτώσεις).
Σε επίπεδο αντικειμένων η παραπάνω σχέση ορίζει ότι το αντικείμενο της κλάσης θα περιέχει πεδία που είναι αντικείμενα άλλων κλάσεων. Με τη σειρά τους τα αντικείμενα αυτά μπορεί να περιέχουν πεδία άλλων κλάσεων κ.ο.κ. Δείτε το παρακάτω παράδειγμα κώδικα που εξηγεί τη σχέση μεταξύ διαφορετικών κλάσεων
class Colour { int r, b, g; } class Box { int width, length, height; } class Ribbon { Colour colour; int length; } class ColouredBox { Colour colour; Box box; } class ColouredBoxWithRibbon { ColouredBox cbox; Ribbon ribbon; }
Δείτε την παραπάνω σχέση κλάσεων, στις κλάσεις αυτές περιέχονται μόνο τα πεδία και παραλείπονται οι κατασκευαστές και μέθοδοι. Η κλάση Colour έχει τρία (3) ακέραια πεδία που προσδιορίζουν τις παραμέτρους RGB για κάθε χρώμα. Η κλάση Βοx έχει τρία (3) ακέραια πεδία που προσδιορίζουν τις διαστάσεις ενός κουτιού. Η κλάση ColouredBox αποτελείται από δύο πεδία που είναι τύπου colour (για το χρώμα) και box (για το κουτί). Επομένως, τα πεδία της κλάση ColouredBox είναι αντικείμενα άλλων κλάσεων.
Αντίστοιχα η κλάση ColouredBoxWithRibbon (χρωματιστό κουτί με κορδέλα), περιέχει τα πεδία cbox (αντικείμενο της κλάσης ColouredBox) και ribbon αντικείμενο της κλάσης Ribbon. Η κλάση Ribbon με τη σειρά της περιέχει τα πεδία colour (τύπου Colour) και το πεδίο length (τύπου int).
Δεν υπάρχει κανένας περιορισμός για το “βάθος” στο οποίο μπορεί να φτάσει η σχέση μεταξύ αντικειμένων διαφορετικών κλάσεων. Επίσης, δεν υπάρχει περιορισμός στον αριθμό των πεδίων που μπορεί να έχει μία κλάση.
Βασικό χαρακτηριστικό όλων των γλωσσών προγραμματισμού είναι ότι επιτρέπουν τον περιορισμό της πρόσβασης σε συγκεκριμένες μεθόδους ή πεδία της κλάσης από άλλες κλάσεις. Ας υποθέσουμε ότι έχουμε τις παρακάτω κλάσεις (ελαφρά διαφοροποιημένες σε σχέση με το προηγούμενο παράδειγμα).
code java> class Colour {
private:
int r, g, b;
public:
int getRed() { return r; }
int getGreen() { return g; }
int getBlue() { return b; }
void setRed(int v) { r = v; }
void setGreen(int v) { g = v; }
void setBlue(int v) { g = v; }
}
class ColouredBox {
private:
int width, length, height;
Colour colour;
public:
void setColour(int vr, int vg, int vb) {
colour.setRed(vr); // δεν επιρέπεται colour.r = vr;
colour.setGreen(vg); // δεν επιρέπεται colour.g = vg;
colour.setRed(vr); // δεν επιρέπεται colour.r = vr;
}
} </code>
Παρατηρήστε ότι η μέθοδος setColour που επιχειρεί να αλλάξει το χρώμα στο κουτί μπορεί να το κάνει μόνο χρησιμοποιώντας τις public μεθόδους setRed, setGreen, setBlue της κλάσης Colour και όχι απευθείας τα πεδία r, g, b της κλάσης αυτής. Ο λόγος που συμβαίνει αυτό είναι διότι τα συγκεκριμένα πεδία είναι δηλωμένα ως private, κατά συνέπεια είναι αδύνατο να προσπελαστούν από την κλάση ColouredBox.
Εύλογα διερωτάται κανείς την σκοπιμότητα χρήσης προσδιοριστών που περιορίζουν την πρόσβαση στα πεδία μία κλάσης. Ο λόγος είναι ότι μέσω των περιορισμών στην προσβασιμότητα, διατηρείται η εσωτερική αυτονομία της κλάσης. Για παράδειγμα η κλάση Colour θα μπορούσε να αλλάξει μελλοντικά την εσωτερική της υλοποίηση και αντί για την απεικόνιση των χρωμάτων με βάση το σύστημα RGB να απεικονίζει τα χρώματα εσωτερικά με βάση το σύστημα HSV. Εφόσον, το εξωτερικό της interface παραμένει το ίδιο, δηλαδή εξακολουθεί να υποστηρίζει τις public μεθόδους getRed, getGreen, getBlue, setRed, setGreen, setBlue και να υποστηρίζει προς τις υπόλοιπες κλάσεις το interface RGB τότε ο τρόπος με τον οποίο αποθηκεύει εσωτερικά την πληροφορία μας είναι αδιάφορος και μπορεί να αλλάξει οποιαδήποτε στιγμή.
Η παραπάνω ιδιότητα του αντικειμενοστραφή προγραμματισμού ονομάζεται ενθυλάκωση (encapsulation) και είναι βασικό δομικό χαρακτηριστικό των γλωσσών αντικειμενοστραφή προγραμματισμού. Μέσω της ενθυλάκωσης επιτυγχάνεται η “απόκρυψη πληροφορίας”. Η “απόκρυψη πληροφορίας” (information hiding), αποτελεί βασικό ζητούμενο στον αντικειμενοστραφή προγραμματισμό διότι επιτυγχάνει την δημιουργία κώδικα που:
Στον πραγματικό κόσμο πολλά πράγματα μοιράζονται κοινά χαρακτηριστικά. Για παράδειγμα:
Με βάση την παραπάνω παρατήρηση, μπορούμε να ορίσουμε κλάσεις που περιγράφουν γενικές έννοιες και στη συνέχεια να τις εξειδικεύσουμε δημιουργώντας νέες κλάσεις που περιγράφουν πιο ειδικές έννοιες. Ο λόγος που θα θέλαμε να κάνουμε κάτι τέτοιο είναι ότι κατά την εξέλιξη του λογισμικού θέλουμε κατά το δυνατόν να επαναχρησιμοποιούμε κώδικα που ήδη έχουμε, δημιουργώντας πιο σύνθετα και εξελιγμένα μοντέλα του υφιστάμενου λογισμικού.
Όταν εφευρέθηκε το ποδήλατο με ταχύτητες, ο εφευρέτης χρησιμοποίησε το υφιστάμενο βασικό σχέδιο του ποδηλάτου για να προσθέσει τον μηχανισμό των ταχυτήτων και να δημιουργήσει τον νέο τύπο ποδηλάτου, το ποδήλατο με ταχύτητες. Σε αναλογία όταν δημιουργήθηκε το πρώτο αυτοκίνητο για κίνηση εκτός δρόμου (τύπου 4×4) αυτό προήλθε ως εξέλιξη του βασικού σχεδίου του αυτοκινήτου διαφοροποιώντας κάποια χαρακτηριστικά στο σχέδιο αυτό. Το βασικό σχέδιο του αυτοκινήτου δεν μπορεί να καλύψει τις ανάγκες κίνησης εκτός δρόμου, αποτελεί όμως τη βάση για την μεταξέλιξη του αυτοκινήτου όχημα κίνησης εκτός δρόμου.
ποδήλατο –> ποδήλατο με ταχύτητες αυτοκίνητο –> αυτοκίνητο για κίνηση εκτός δρόμου
Σε αναλογία με τα παραπάνω, η κληρονομικότητα μας επιτρέπει να δημιουργήσουμε νέες κλάσεις με αφετηρία υφιστάμενες. Η ιδιότητα της κληρονομικότητας δηλώνει ότι δεν θα χρειαστεί να ξαναγράψουμε το σύνολο της νέας κλάσης από την αρχή. Αντίθετα, ο μεταγλωττιστής της γλώσσας ενσωματώνει αυτόμτα στη νέα κλάση τα χαρακτηριστικά της γονικής κλάσης. Ο προγραμματιστής αρκεί να προσθέσει ότι επιπλέον χρειάζεται προκειμένου να δημιουργήσει τη νέα κλάση, η οποία επεκτείνει την αρχική ώστε αυτή να παράγει τα νέου τύπου αντικείμενα.
Μέσω της κληρονομικότητας υλοποιείται μία από τις βασικές αρχές του αντικειμενοστραφή προγραμματισμού που είναι η αρχή της μέγιστης επαναχρησιμοποίησης υφιστάμενου κώδικα.
Επεκτείνοντας την παραπάνω συλλογιστική μπορούμε να έχουμε πολλαπλές ιεραρχίες κλάσεων. Για παράδειγμα, από το ποδήλατο με ταχύτητες μπορεί να οριστεί το ποδήλατο για δύο επιβάτες με ταχύτητες ή το ποδήλατο για δύο επιβάτες με ταχύτητες και αμορτισέρ.
ποδήλατο –> ποδήλατο με ταχύτητες –> ποδήλατο με ταχύτητες για δύο επιβάτες → ποδήλατο με ταχύτητες και αμορτισέρ για δύο επιβάτες.
Για το ποδήλατο με ταχύτητες η κλάση ποδήλατο αποτελεί την γονική κλάση (Super Class). Αντίστοιχα για το ποδήλατο, το ποδήλατο με ταχύτητες αποτελεί υποκλάση (Sub Class) αυτού.
Τα αντικείμενα στον πραγματικό κόσμο ορίζουν την διεπαφή τους με τον έξω κόσμο μέσα από συγκεκριμένα εργαλεία που καταλήγουν σε συγκεκριμένες πράξεις. Για παράδειγμα,
Ανάλογη είναι η λειτουργία της διεπαφής (interface) για τον αντικειμενοστραφή προγραμματισμό. Ορίζουμε μία διεπαφή, ως ένα σύνολο από μεθόδους (δηλ. τρόπους αλληλεπίδρασης με τα αντικείμενα), δίνοντας μόνο τους ορισμούς των μεθόδων, χωρίς την υλοποίηση τους. Εάν μία κλάση υλοποιεί ΟΛΕΣ τις μεθόδους μιας διεπαφής, τότε η κλάση είναι σύμφωνη με την συγκεκριμένη διεπαφή. Ο τρόπος που υλοποιεί κάθε κλάση τις μεθόδους της διεπαφής είναι εσωτερικό θέμα της κλάσης και δεν ελέγχεται από την διεπαφή. Επιπλέον, μία κλάση μπορεί να υλοποιεί μία ή περισσότερες διεπαφές.
Ας υποθέσουμε ότι ορίζεται η διεπαφή Stack (στοίβα) η οποία περιγράφει ένα σύνολο μεθόδων που πρέπει να υλοποιούνται από μία κλάση προκειμένου τα αντικείμενα της κλάσης αυτής να ικανοποιούν τη στοίβα. Ως γνωστόν οι μέθοδοι που απαιτείται να υλοποιεί μία στοίβα είναι οι παρακάτω:
Αν οποιαδήποτε κλάση υλοποιεί τις παραπάνω μεθόδους τότε μπορούμε να πούμε ότι υλοποιεί την διεπαφή της στοίβας (interface Stack).
Στον αντικειμενοστραφή προγραμματισμό, όσες κλάσεις υλοποιούν ΟΛΕΣ τις μεθόδους ενός interface, υλοποιούν συνολικά το interface.
| Προηγούμενο: Εντολές τερματισμού και ελέγχου της ανακύκλωσης Περιεχόμενα | Επόμενο: Η κλάση | |