Προγραμματισμός

Σχεδιασμός με στατικά μέλη

Αν και η Java είναι αντικειμενοστραφής σε μεγάλο βαθμό, δεν είναι ΚΑΘΑΡΟΣ αντικειμενοστραφής γλώσσα. Ένας από τους λόγους για τους οποίους η Java δεν είναι καθαρά αντικειμενοστραφής είναι ότι δεν είναι όλα τα αντικείμενα σε αυτό. Για παράδειγμα, η Java σάς επιτρέπει να δηλώνετε μεταβλητές πρωτόγονων τύπων (int, φλοτέρ, boolean, κλπ.) που δεν είναι αντικείμενα. Και η Java έχει στατικά πεδία και μεθόδους, που είναι ανεξάρτητες και χωριστές από αντικείμενα. Αυτό το άρθρο παρέχει συμβουλές σχετικά με τον τρόπο χρήσης στατικών πεδίων και μεθόδων σε ένα πρόγραμμα Java, διατηρώντας παράλληλα μια αντικειμενοστρεφή εστίαση στα σχέδιά σας.

Η διάρκεια ζωής μιας κλάσης σε μια εικονική μηχανή Java (JVM) έχει πολλές ομοιότητες με τη διάρκεια ζωής ενός αντικειμένου. Ακριβώς όπως ένα αντικείμενο μπορεί να έχει κατάσταση, που αντιπροσωπεύεται από τις τιμές των μεταβλητών παρουσίας του, μια κλάση μπορεί να έχει κατάσταση, που αντιπροσωπεύεται από τις τιμές των μεταβλητών κλάσης. Ακριβώς όπως το JVM ορίζει μεταβλητές παρουσίας σε προεπιλεγμένες αρχικές τιμές πριν από την εκτέλεση κώδικα αρχικοποίησης, το JVM ορίζει μεταβλητές κλάσης σε προεπιλεγμένες αρχικές τιμές πριν από την εκτέλεση κώδικα αρχικοποίησης. Και όπως τα αντικείμενα, τα μαθήματα μπορούν να συλλέγονται σκουπίδια εάν δεν αναφέρονται πλέον από την εφαρμογή που εκτελείται.

Ωστόσο, υπάρχουν σημαντικές διαφορές μεταξύ τάξεων και αντικειμένων. Ίσως η πιο σημαντική διαφορά είναι ο τρόπος με τον οποίο χρησιμοποιούνται οι μέθοδοι παρουσίας και τάξης: οι μέθοδοι παρουσίας είναι (ως επί το πλείστον) δυναμικά δεσμευμένες, αλλά οι μέθοδοι κατηγορίας είναι στατικά δεσμευμένες. (Σε τρεις ειδικές περιπτώσεις, οι μέθοδοι παρουσίας δεν δεσμεύονται δυναμικά: επίκληση μεθόδων ιδιωτικής παρουσίας, επίκληση του μέσα σε αυτό μεθόδους (κατασκευαστές) και επίκληση με το σούπερ λέξη-κλειδί. Δείτε τους πόρους για περισσότερες πληροφορίες.)

Μια άλλη διαφορά μεταξύ κλάσεων και αντικειμένων είναι ο βαθμός απόκρυψης δεδομένων που παρέχεται από τα επίπεδα ιδιωτικής πρόσβασης. Εάν μια μεταβλητή παρουσίας δηλώνεται ιδιωτική, μόνο οι μέθοδοι παρουσίας μπορούν να έχουν πρόσβαση σε αυτήν. Αυτό σας δίνει τη δυνατότητα να διασφαλίσετε την ακεραιότητα των δεδομένων παρουσίας και να κάνετε αντικείμενα ασφαλή στο νήμα. Το υπόλοιπο πρόγραμμα δεν μπορεί να έχει άμεση πρόσβαση σε αυτές τις μεταβλητές παρουσίας, αλλά πρέπει να ακολουθήσει τις μεθόδους παρουσίας για να χειριστεί τις μεταβλητές παρουσίας. Σε μια προσπάθεια να κάνει μια τάξη να συμπεριφέρεται σαν ένα καλά σχεδιασμένο αντικείμενο, μπορείτε να κάνετε τις μεταβλητές τάξης ιδιωτικές και να ορίσετε μεθόδους τάξης που τις χειρίζονται. Παρ 'όλα αυτά, δεν λαμβάνετε τόσο καλή εγγύηση για την ασφάλεια του νήματος ή ακόμα και την ακεραιότητα των δεδομένων με αυτόν τον τρόπο, επειδή ένα συγκεκριμένο είδος κώδικα έχει ένα ειδικό προνόμιο που τους δίνει άμεση πρόσβαση σε μεταβλητές ιδιωτικής κλάσης: μεθόδους παρουσίας και ακόμη και αρχικοποιητές παρουσίας μεταβλητές, μπορούν να έχουν άμεση πρόσβαση σε αυτές τις ιδιωτικές μεταβλητές κλάσης.

Έτσι, τα στατικά πεδία και οι μέθοδοι των τάξεων, αν και μοιάζουν με πολλούς τρόπους με τα πεδία παρουσίας και τις μεθόδους αντικειμένων, έχουν σημαντικές διαφορές που θα πρέπει να επηρεάσουν τον τρόπο που τα χρησιμοποιείτε στα σχέδια.

Αντιμετώπιση τάξεων ως αντικειμένων

Καθώς σχεδιάζετε προγράμματα Java, πιθανότατα θα συναντήσετε πολλές καταστάσεις στις οποίες αισθάνεστε την ανάγκη για ένα αντικείμενο που λειτουργεί με κάποιους τρόπους όπως μια τάξη. Μπορεί, για παράδειγμα, να θέλετε ένα αντικείμενο του οποίου η διάρκεια ζωής ταιριάζει με εκείνη μιας τάξης. Ή μπορεί να θέλετε ένα αντικείμενο που, όπως μια τάξη, περιορίζεται σε ένα μόνο παράδειγμα σε ένα συγκεκριμένο όνομα χώρου.

Σε καταστάσεις σχεδιασμού όπως αυτές, μπορεί να είναι δελεαστικό να δημιουργήσετε μια τάξη και να τη χρησιμοποιήσετε σαν αντικείμενο για να ορίσετε μεταβλητές τάξης, να τις κάνετε ιδιωτικές και να ορίσετε ορισμένες μεθόδους δημόσιας τάξης που χειρίζονται τις μεταβλητές τάξης. Όπως ένα αντικείμενο, μια τέτοια τάξη έχει κατάσταση. Όπως ένα καλά σχεδιασμένο αντικείμενο, οι μεταβλητές που ορίζουν την κατάσταση είναι ιδιωτικές και ο εξωτερικός κόσμος μπορεί να επηρεάσει αυτήν την κατάσταση μόνο με την επίκληση των μεθόδων κλάσης.

Δυστυχώς, υπάρχουν ορισμένα προβλήματα με αυτήν την προσέγγιση "class-as-object". Επειδή οι μέθοδοι τάξης είναι στατικά δεσμευμένες, η τάξη ως αντικείμενο δεν θα απολαμβάνει τα οφέλη ευελιξίας του πολυμορφισμού και της αναβάθμισης. (Για τους ορισμούς του πολυμορφισμού και της δυναμικής δέσμευσης, ανατρέξτε στο άρθρο «Τεχνικές σχεδιασμού», «Σύνθεση έναντι κληρονομικότητας»). Ο πολυμορφισμός είναι δυνατός και χρήσιμος, με δυναμική δέσμευση, αλλά οι μέθοδοι κατηγορίας δεν δεσμεύονται δυναμικά. Εάν κάποιος υποτάξει την τάξη ως αντικείμενο, δεν θα μπορεί να το κάνει καταπατώ τις μεθόδους τάξης σας, δηλώνοντας τις μεθόδους τάξης με το ίδιο όνομα. θα μπορούν μόνο κρύβω τους. Όταν καλείται μία από αυτές τις επαναπροσδιορισμένες μεθόδους κλάσης, η JVM θα επιλέξει την εφαρμογή της μεθόδου που θα εκτελεστεί όχι από την κλάση ενός αντικειμένου κατά το χρόνο εκτέλεσης, αλλά από τον τύπο μιας μεταβλητής κατά το χρόνο μεταγλώττισης.

Επιπλέον, η ασφάλεια του νήματος και η ακεραιότητα των δεδομένων που επιτυγχάνεται με την σχολαστική εφαρμογή των μεθόδων κλάσης στο class-as-αντικείμενο σας είναι σαν ένα σπίτι χτισμένο από άχυρο. Η ασφάλεια του νήματος και η ακεραιότητα των δεδομένων σας θα είναι εγγυημένα εφόσον όλοι χρησιμοποιούν τις μεθόδους κλάσης για να χειριστούν την κατάσταση που είναι αποθηκευμένη στις μεταβλητές κλάσης. Αλλά ένας απρόσεκτος ή ανίδεος προγραμματιστής θα μπορούσε, με την προσθήκη μιας μεθόδου παρουσίας που θα έχει άμεση πρόσβαση στις μεταβλητές της ιδιωτικής σας κατηγορίας, ακούσια και φουσκωμένος και θα χτυπήσει την ασφάλεια του νήματος και την ακεραιότητα των δεδομένων σας.

Για αυτόν τον λόγο, η βασική μου οδηγία σχετικά με τις μεταβλητές τάξης και τις μεθόδους τάξης είναι:

Μην αντιμετωπίζετε τάξεις σαν αντικείμενα.

Με άλλα λόγια, μην σχεδιάζετε με στατικά πεδία και μεθόδους μιας τάξης σαν να ήταν τα πεδία παρουσίας και οι μέθοδοι ενός αντικειμένου.

Εάν θέλετε κάποια κατάσταση και συμπεριφορά των οποίων η διάρκεια ζωής ταιριάζει με εκείνη μιας κλάσης, αποφύγετε τη χρήση μεταβλητών τάξης και μεθόδων κλάσης για την προσομοίωση ενός αντικειμένου. Αντ 'αυτού, δημιουργήστε ένα πραγματικό αντικείμενο και χρησιμοποιήστε μια μεταβλητή κλάσης για να κρατήσετε μια αναφορά σε αυτό και μεθόδους κλάσης για να παρέχετε πρόσβαση στην αναφορά αντικειμένου. Εάν θέλετε να διασφαλίσετε ότι υπάρχει μόνο μία παρουσία κάποιας κατάστασης και συμπεριφοράς σε ένα μόνο όνομα χώρου, μην προσπαθήσετε να σχεδιάσετε μια κλάση που προσομοιώνει ένα αντικείμενο. Αντ 'αυτού, δημιουργήστε ένα μοναδικό χαρτί - ένα αντικείμενο με εγγύηση ότι έχει μόνο μία παρουσία ανά χώρο ονόματος.

Τι είναι λοιπόν καλό για τα μέλη της τάξης;

Κατά τη γνώμη μου, η καλύτερη νοοτροπία που πρέπει να καλλιεργήσετε κατά το σχεδιασμό προγραμμάτων Java είναι να σκεφτείτε αντικείμενα, αντικείμενα, αντικείμενα. Επικεντρωθείτε στο σχεδιασμό εξαιρετικών αντικειμένων και σκεφτείτε τις τάξεις κυρίως ως σχεδιαγράμματα για αντικείμενα - τη δομή στην οποία ορίζετε τις μεταβλητές παρουσίας και τις μεθόδους παρουσίας που συνθέτουν τα καλά σχεδιασμένα αντικείμενα σας. Εκτός αυτού, μπορείτε να θεωρήσετε ότι τα μαθήματα παρέχουν μερικές ειδικές υπηρεσίες που δεν μπορούν να παρέχουν αντικείμενα ή δεν μπορούν να παρέχουν τόσο κομψά. Σκεφτείτε τα μαθήματα ως:

  • το κατάλληλο μέρος για τον ορισμό των "μεθόδων χρησιμότητας" (μέθοδοι που λαμβάνουν είσοδο και παρέχουν έξοδο μόνο μέσω παραμέτρων που έχουν περάσει και της τιμής επιστροφής)
  • ένας τρόπος ελέγχου της πρόσβασης σε αντικείμενα και δεδομένα

Μέθοδοι χρησιμότητας

Μέθοδοι που δεν χειρίζονται ή χρησιμοποιούν την κατάσταση ενός αντικειμένου ή τάξης που ονομάζω "μεθόδους χρησιμότητας". Οι μέθοδοι χρησιμότητας απλώς επιστρέφουν κάποια τιμή (ή τιμές) που υπολογίζεται αποκλειστικά από δεδομένα που μεταβιβάζονται στη μέθοδο ως παραμέτρους. Πρέπει να κάνετε τέτοιες μεθόδους στατικές και να τις τοποθετήσετε στην τάξη που σχετίζεται περισσότερο με την υπηρεσία που παρέχει η μέθοδος.

Ένα παράδειγμα μιας μεθόδου χρησιμότητας είναι το String copyValueOf (char [] δεδομένα) μέθοδος τάξης Σειρά. Αυτή η μέθοδος παράγει την παραγωγή της, μια τιμή επιστροφής του τύπου Σειρά, αποκλειστικά από την παράμετρο εισόδου, μια σειρά από απανθρακώνωμικρό. Επειδή copyValueOf () ούτε χρησιμοποιεί ούτε επηρεάζει την κατάσταση οποιουδήποτε αντικειμένου ή κλάσης, είναι μια μέθοδος χρησιμότητας. Και, όπως πρέπει να είναι όλες οι μέθοδοι χρησιμότητας, copyValueOf () είναι μια μέθοδος τάξης.

Έτσι ένας από τους κύριους τρόπους χρήσης μεθόδων κατηγορίας είναι ως μέθοδοι χρησιμότητας - μέθοδοι που επιστρέφουν την παραγωγή που υπολογίζεται αποκλειστικά από παραμέτρους εισόδου. Άλλες χρήσεις μεθόδων κατηγορίας περιλαμβάνουν μεταβλητές τάξης.

Μεταβλητές κατηγορίας για απόκρυψη δεδομένων

Μία από τις θεμελιώδεις αρχές στον αντικειμενοστρεφή προγραμματισμό είναι απόκρυψη δεδομένων - περιορισμός της πρόσβασης σε δεδομένα για ελαχιστοποίηση των εξαρτήσεων μεταξύ των τμημάτων ενός προγράμματος. Εάν ένα συγκεκριμένο κομμάτι δεδομένων έχει περιορισμένη προσβασιμότητα, αυτά τα δεδομένα μπορούν να αλλάξουν χωρίς να σπάσουν τα τμήματα του προγράμματος που δεν έχουν πρόσβαση στα δεδομένα.

Εάν, για παράδειγμα, ένα αντικείμενο απαιτείται μόνο από περιπτώσεις μιας συγκεκριμένης κλάσης, μια αναφορά σε αυτό μπορεί να αποθηκευτεί σε μια μεταβλητή ιδιωτικής κλάσης. Αυτό δίνει σε όλες τις παρουσίες αυτής της κλάσης εύκολη πρόσβαση σε αυτό το αντικείμενο - οι παρουσίες το χρησιμοποιούν απλώς - αλλά κανένας άλλος κώδικας οπουδήποτε αλλού στο πρόγραμμα δεν μπορεί να το καταλάβει. Με παρόμοιο τρόπο, μπορείτε να χρησιμοποιήσετε την πρόσβαση πακέτων και τις μεταβλητές κατηγορίας προστατευμένης κλάσης για να μειώσετε την ορατότητα των αντικειμένων που πρέπει να κοινοποιούνται από όλα τα μέλη ενός πακέτου και υποκατηγοριών.

Οι μεταβλητές δημόσιας τάξης είναι μια διαφορετική ιστορία. Εάν μια μεταβλητή δημόσιας τάξης δεν είναι τελική, είναι μια παγκόσμια μεταβλητή: αυτή η άσχημη κατασκευή που είναι η αντίθεση της απόκρυψης δεδομένων. Δεν υπάρχει ποτέ δικαιολογία για μια μεταβλητή δημόσιας τάξης, εκτός εάν είναι τελική.

Οι τελικές δημόσιες μεταβλητές κλάσης, είτε πρωτόγονος τύπος είτε αντικείμενο αναφοράς, εξυπηρετούν έναν χρήσιμο σκοπό. Μεταβλητές πρωτόγονων τύπων ή τύπου Σειρά είναι απλώς σταθερές, οι οποίες γενικά βοηθούν να καταστούν τα προγράμματα πιο ευέλικτα (ευκολότερα στην αλλαγή). Ο κώδικας που χρησιμοποιεί σταθερές είναι πιο εύκολο να αλλάξει επειδή μπορείτε να αλλάξετε τη σταθερή τιμή σε ένα μέρος. Οι μεταβλητές δημόσιας τελικής κλάσης των τύπων αναφοράς σάς επιτρέπουν να παρέχετε καθολική πρόσβαση σε αντικείμενα που χρειάζονται παγκοσμίως. Για παράδειγμα, System.in, System.out, και System.err είναι δημόσιες μεταβλητές τελικής κλάσης που παρέχουν καθολική πρόσβαση στις τυπικές ροές εξόδου και σφάλματος εισόδου.

Επομένως, ο κύριος τρόπος για να δείτε τις μεταβλητές τάξης είναι ως ένας μηχανισμός για τον περιορισμό της προσβασιμότητας των μεταβλητών ή των αντικειμένων (που σημαίνει, απόκρυψη). Όταν συνδυάζετε μεθόδους κλάσης με μεταβλητές τάξης, μπορείτε να εφαρμόσετε ακόμη πιο περίπλοκες πολιτικές πρόσβασης.

Χρήση μεθόδων κλάσης με μεταβλητές κλάσης

Εκτός από τη χρήση ως βοηθητικών μεθόδων, μέθοδοι κλάσης μπορούν να χρησιμοποιηθούν για τον έλεγχο της πρόσβασης σε αντικείμενα που είναι αποθηκευμένα σε μεταβλητές κλάσης - ειδικότερα, για τον έλεγχο του τρόπου δημιουργίας ή διαχείρισης των αντικειμένων. Δύο παραδείγματα αυτής της μεθόδου κατηγορίας είναι το setSecurityManager () και getSecurityManager () μέθοδοι της τάξης Σύστημα. Ο διαχειριστής ασφαλείας για μια εφαρμογή είναι ένα αντικείμενο που, όπως η τυπική ροή εισόδου, εξόδου και σφάλματος, απαιτείται σε πολλά διαφορετικά μέρη. Σε αντίθεση με τα τυπικά αντικείμενα ροής I / O, ωστόσο, η αναφορά στον διαχειριστή ασφαλείας δεν αποθηκεύεται σε μια δημόσια μεταβλητή τελικής κλάσης. Το αντικείμενο διαχείρισης ασφάλειας αποθηκεύεται σε μια μεταβλητή ιδιωτικής κλάσης και οι μέθοδοι set and get εφαρμόζουν μια ειδική πολιτική πρόσβασης για το αντικείμενο.

Το μοντέλο ασφαλείας της Java θέτει έναν ειδικό περιορισμό στον διαχειριστή ασφαλείας. Πριν από την Java 2 (παλαιότερα γνωστή ως JDK 1.2), μια εφαρμογή ξεκίνησε τη ζωή της χωρίς διαχειριστή ασφαλείας (getSecurityManager () Επέστρεψαν μηδενικό). Η πρώτη κλήση προς setSecurityManager () καθιέρωσε τον διαχειριστή ασφαλείας, ο οποίος στη συνέχεια δεν επιτρέπεται να αλλάξει. Τυχόν επακόλουθες κλήσεις προς setSecurityManager () θα απέφερε μια εξαίρεση ασφαλείας. Στην Java 2, η εφαρμογή ξεκινά πάντα με έναν διαχειριστή ασφαλείας, αλλά παρόμοια με τις προηγούμενες εκδόσεις, το setSecurityManager () μέθοδος θα σας επιτρέψει αλλαγή ο διαχειριστής ασφαλείας μία φορά, το πολύ.

Ο διαχειριστής ασφαλείας παρέχει ένα καλό παράδειγμα για το πώς μπορούν να χρησιμοποιηθούν μέθοδοι κλάσης σε συνδυασμό με μεταβλητές ιδιωτικής κλάσης για την εφαρμογή ειδικής πολιτικής πρόσβασης για αντικείμενα που αναφέρονται από τις μεταβλητές κλάσης. Εκτός από τις βοηθητικές μεθόδους, σκεφτείτε τις μεθόδους κατηγορίας ως το μέσο για τη θέσπιση ειδικών πολιτικών πρόσβασης για αναφορές αντικειμένων και δεδομένα που είναι αποθηκευμένα σε μεταβλητές κλάσης.

Κατευθυντήριες γραμμές

Το κύριο σημείο συμβουλών που δίνεται σε αυτό το άρθρο είναι:

Μην αντιμετωπίζετε τάξεις σαν αντικείμενα.

Εάν χρειάζεστε ένα αντικείμενο, δημιουργήστε ένα αντικείμενο. Περιορίστε τη χρήση μεταβλητών κατηγορίας και μεθόδων για τον καθορισμό μεθόδων χρησιμότητας και την εφαρμογή ειδικών ειδών πολιτικών πρόσβασης για αντικείμενα και πρωτόγονους τύπους που αποθηκεύονται σε μεταβλητές κλάσης. Αν και δεν είναι μια καθαρή αντικειμενοστρεφής γλώσσα, η Java ωστόσο είναι αντικειμενοστραφής σε μεγάλο βαθμό και τα σχέδιά σας θα πρέπει να αντικατοπτρίζουν αυτό. Σκεφτείτε αντικείμενα.

Τον επόμενο μήνα

Τον επόμενο μήνα Τεχνικές σχεδιασμού Το άρθρο θα είναι το τελευταίο αυτής της στήλης. Σύντομα θα αρχίσω να γράφω ένα βιβλίο με βάση το υλικό των Τεχνικών Σχεδιασμού, Ευέλικτη Java, και θα τοποθετήσω αυτό το υλικό στον ιστότοπό μου καθώς πηγαίνω. Ακολουθήστε λοιπόν αυτό το έργο και στείλτε μου σχόλια Μετά από ένα διάλειμμα ενός ή δύο μηνών, θα επιστρέψω JavaWorld και SunWorld με μια νέα στήλη επικεντρωμένη στον Jini.

Ένα αίτημα για συμμετοχή του αναγνώστη

Ενθαρρύνω τα σχόλιά σας, τις κριτικές, τις προτάσεις, τις φλόγες - όλα τα είδη σχολίων - σχετικά με το υλικό που παρουσιάζεται σε αυτήν τη στήλη. Εάν διαφωνείτε με κάτι ή θέλετε να προσθέσετε κάτι, ενημερώστε μας.

Μπορείτε να συμμετάσχετε σε ένα φόρουμ συζήτησης αφιερωμένο σε αυτό το υλικό, να εισαγάγετε ένα σχόλιο μέσω της φόρμας στο κάτω μέρος του άρθρου, ή να μου στείλετε μήνυμα ηλεκτρονικού ταχυδρομείου απευθείας χρησιμοποιώντας τον σύνδεσμο που παρέχεται στο βιογραφικό μου παρακάτω.

Ο Bill Venners γράφει λογισμικό επαγγελματικά για 12 χρόνια. Με έδρα τη Silicon Valley, παρέχει υπηρεσίες παροχής συμβουλών και εκπαίδευσης λογισμικού με το όνομα Artima Software Company. Με τα χρόνια έχει αναπτύξει λογισμικό για τις βιομηχανίες ηλεκτρονικών ειδών ευρείας κατανάλωσης, εκπαίδευσης, ημιαγωγών και ασφάλισης ζωής. Έχει προγραμματίσει σε πολλές γλώσσες σε πολλές πλατφόρμες: γλώσσα συναρμολόγησης σε διάφορους μικροεπεξεργαστές, C στο Unix, C ++ σε Windows, Java στον Ιστό. Είναι συγγραφέας του βιβλίου Inside the Java Virtual Machine, που εκδόθηκε από τον McGraw-Hill.