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

Διεπαφές σε Java

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

Θα μάθετε επίσης πώς έχει εξελιχθεί η διεπαφή στο Java 8, με την προσθήκη προεπιλεγμένων και στατικών μεθόδων και στο Java 9 με τις νέες ιδιωτικές μεθόδους. Αυτές οι προσθήκες καθιστούν τις διεπαφές πιο χρήσιμες για έμπειρους προγραμματιστές. Δυστυχώς, θολώνουν επίσης τις γραμμές μεταξύ τάξεων και διεπαφών, καθιστώντας τον προγραμματισμό διεπαφής ακόμη πιο συγκεχυμένο για αρχάριους Java.

λήψη Λήψη του κώδικα Λήψη του πηγαίου κώδικα για παράδειγμα εφαρμογές σε αυτό το σεμινάριο. Δημιουργήθηκε από τον Jeff Friesen για το JavaWorld.

Τι είναι η διεπαφή Java;

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

System.out.println (μέσος όρος (10, 15)); διπλός μέσος όρος (διπλός x, διπλός y) // διεπαφή μεταξύ μέσου όρου (10, 15) κλήσης και επιστροφής (x + y) / 2; {επιστροφή (x + y) / 2; }

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

Λίστα 1. Η κλάση λογαριασμού και η διεπαφή της

λογαριασμός κλάσης {ιδιωτικό όνομα συμβολοσειράς; ιδιωτικό μεγάλο ποσό · Λογαριασμός (όνομα συμβολοσειράς, μεγάλο ποσό) {this.name = name; setAmount (ποσό); } άκυρη κατάθεση (μεγάλο ποσό) {this.amount + = ποσό; } String getName () {όνομα επιστροφής; } μακρύ getAmount () {ποσό επιστροφής; } void setAmount (μεγάλο ποσό) {this.amount = ποσό; }}

ο Λογαριασμός (Όνομα συμβολοσειράς, μεγάλο ποσό) κατασκευαστής και το άκυρη κατάθεση (μεγάλο ποσό), Συμβολοσειρά getName (), μακρύ getAmount (), και void setAmount (μεγάλο ποσό) οι μέθοδοι αποτελούν το λογαριασμός διεπαφή κλάσης: είναι προσβάσιμα σε εξωτερικό κώδικα. ο ιδιωτικό όνομα συμβολοσειράς; και ιδιωτικό μεγάλο ποσό · τα πεδία δεν είναι προσβάσιμα.

Περισσότερα για τις διεπαφές Java

Τι μπορείτε να κάνετε με διεπαφές στα προγράμματα Java; Λάβετε μια επισκόπηση με τους έξι ρόλους του Jeff της διεπαφής Java.

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

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

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

Λίστα ονομάτων = νέα ArrayList () άκυρη εκτύπωση (ονόματα λίστας) {// ...}

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

Λίστα είναι μια διεπαφή Java που περιγράφει μια διαδοχική συλλογή αντικειμένων. Λίστα Array είναι μια κλάση που περιγράφει μια εφαρμογή που βασίζεται σε πίνακα Λίστα Διεπαφή Java. Μια νέα παρουσία του Λίστα Array η τάξη λαμβάνεται και ανατίθεται σε Λίστα μεταβλητός ονόματα. (Λίστα και Λίστα Array αποθηκεύονται στις τυπικές βιβλιοθήκες τάξης java.util πακέτο.)

Γωνιακές αγκύλες και γενικά

Οι γωνιακές αγκύλες (< και >) είναι μέρος του σετ λειτουργιών γενικής χρήσης Java. Το δείχνουν αυτό ονόματα περιγράφει μια λίστα συμβολοσειρών (μόνο οι συμβολοσειρές μπορούν να αποθηκευτούν στη λίστα). Θα παρουσιάσω γενικά σε ένα μελλοντικό άρθρο Java 101.

Όταν αλληλεπιδρά ο κωδικός πελάτη ονόματα, θα επικαλεστεί εκείνες τις μεθόδους που δηλώνονται από Λίστα, και τα οποία υλοποιούνται από Λίστα Array. Ο κωδικός πελάτη δεν θα αλληλεπιδράσει άμεσα με Λίστα Array. Ως αποτέλεσμα, ο κωδικός πελάτη δεν θα σπάσει όταν μια διαφορετική κλάση υλοποίησης, όπως Συνδεδεμένη λίστα, απαιτείται:

Λίστα ονομάτων = νέα LinkedList () // ... άκυρη εκτύπωση (ονόματα λίστας) {// ...}

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

Αποσύνδεση Λίστα από Λίστα Array και Συνδεδεμένη λίστα σας επιτρέπει να γράψετε κώδικα που είναι απρόσβλητος από αλλαγές στην εφαρμογή της τάξης. Χρησιμοποιώντας διεπαφές Java, μπορείτε να αποφύγετε προβλήματα που θα μπορούσαν να προκύψουν από την εξάρτηση από κλάσεις υλοποίησης. Αυτή η αποσύνδεση είναι ο κύριος λόγος για τη χρήση διεπαφών Java.

Δήλωση διεπαφών Java

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

διεπαφή αναγνωριστικό {// σώμα διεπαφής}

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

Η Λίστα 2 δηλώνει μια διεπαφή που ονομάζεται Σχεδίαση.

Λίστα 2. Ένα παράδειγμα διεπαφής Java

Σχέδιο διεπαφής {int RED = 1; int ΠΡΑΣΙΝΟ = 2; int BLUE = 3; int ΜΑΥΡΟ = 4; int ΛΕΥΚΟ = 5; άκυρη κλήρωση (int χρώμα) }

Διεπαφές στη βασική βιβλιοθήκη κατηγορίας Java

Ως σύμβαση ονομασίας, πολλές διεπαφές στην τυπική βιβλιοθήκη κλάσης Java τελειώνουν με το ικανός κατάληξη. Τα παραδείγματα περιλαμβάνουν Καλείται, Κλωνοποιήσιμο, Συγκρίσιμος, Μορφοποιήσιμος, Επαληθεύσιμο, Τρέξιμο, Σειριοποιήσιμο, και Μεταβιβάσιμος. Ωστόσο, το επίθημα δεν είναι υποχρεωτικό. η τυπική βιβλιοθήκη κατηγορίας περιλαμβάνει τις διεπαφές CharSequence, Πρόχειρο, Συλλογή, Εκτελεστής διαθήκης, Μελλοντικός, Επαναληπτής, Λίστα, Χάρτης και πολλοί άλλοι.

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

Προεπιλογές κεφαλίδας πεδίου και μεθόδου

Τα πεδία που δηλώνονται σε μια διεπαφή είναι σιωπηρά δημόσιο τελικό στατικό. Οι κεφαλίδες μιας διεπαφής είναι σιωπηρά δημόσια περίληψη.

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

Διεπαφές σήμανσης και ετικετών

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

Εφαρμογή διεπαφών Java

Μια τάξη εφαρμόζει μια διεπαφή προσαρτώντας Java υλοποιεί λέξη-κλειδί ακολουθούμενη από μια λίστα ονομάτων διασύνδεσης διαχωρισμένη με κόμμα στην κεφαλίδα κλάσης και κωδικοποιώντας κάθε μέθοδο διεπαφής στην τάξη. Η Λίστα 3 παρουσιάζει μια κλάση που εφαρμόζει την Καταχώριση 2 Σχεδίαση διεπαφή.

Λίστα 3. Κύκλος υλοποίησης της διεπαφής Drawable

η κατηγορία Circle υλοποιεί Drawable {private double x, y, radius; Κύκλος (διπλό x, διπλό y, διπλή ακτίνα) {this.x = x; αυτό.y = y; this.radius = ακτίνα; } @Override public void draw (int color) {System.out.println ("Circle draw at (" + x + "," + y + "), with radius" + radius + ", and color" + color); } διπλή getRadius () {ακτίνα επιστροφής; } διπλό getX () {return x; } διπλό getY () {return y; }}

Λίστα 3's Κύκλος τάξη περιγράφει έναν κύκλο ως κεντρικό σημείο και ακτίνα. Εκτός από την παροχή ενός κατασκευαστή και κατάλληλων μεθόδων λήψης, Κύκλος εφαρμόζει το Σχεδίαση διεπαφή με προσάρτηση υλοποιεί Drawable στο Κύκλος κεφαλίδα και με παράκαμψη (όπως υποδεικνύεται από το @Καταπατώ σχόλιο) Σχεδίαση'μικρό σχεδιάζω() κεφαλίδα μεθόδου.

Η λίστα 4 παρουσιάζει ένα δεύτερο παράδειγμα: α Ορθογώνιο παραλληλόγραμμο τάξη που εφαρμόζει επίσης Σχεδίαση.

Λίστα 4. Εφαρμογή της διεπαφής με δυνατότητα σχεδίασης σε περιβάλλον ορθογωνίου

η κατηγορία ορθογωνίου εφαρμόζει Drawable {private double x1, y1, x2, y2; Ορθογώνιο (διπλό x1, διπλό y1, διπλό x2, διπλό y2) {this.x1 = x1; αυτό.y1 = y1; αυτό.x2 = x2; αυτό.y2 = y2; } @Override public void draw (int color) {System.out.println ("ορθογώνιο σχέδιο με επάνω αριστερή γωνία στο (" + x1 + "," + y1 + ") και κάτω δεξιά γωνία στο (" + x2 + "," + y2 + ") και χρώμα" + χρώμα); } διπλό getX1 () {return x1; } διπλό getX2 () {return x2; } διπλό getY1 () {return y1; } διπλό getY2 () {return y2; }}

Λίστα 4's Ορθογώνιο παραλληλόγραμμο Η κλάση περιγράφει ένα ορθογώνιο ως ζεύγος σημείων που υποδηλώνουν την άνω αριστερή και την κάτω δεξιά γωνία αυτού του σχήματος. Οπως και με Κύκλος, Ορθογώνιο παραλληλόγραμμο παρέχει έναν κατασκευαστή και κατάλληλες μεθόδους λήψης, και εφαρμόζει επίσης το Σχεδίαση διεπαφή.

Επικαλυπτόμενες κεφαλίδες μεθόδου διεπαφής

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

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

Λίστα 5. Ψευδώνυμα αντικείμενα Κύκλου και ορθογωνίου ως Drawables

class Draw {public static void main (String [] args) {Drawable [] drawables = new Drawable [] {new Circle (10, 20, 15), new Circle (30, 20, 10), νέο ορθογώνιο (5, 8 , 8, 9)}; για (int i = 0; i <drawables.length; i ++) drawables [i] .draw (Drawable.RED); }}

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

Υποθέτοντας ότι η Λίστα 2 αποθηκεύεται σε ένα Drawable.java αρχείο προέλευσης, το οποίο βρίσκεται στον ίδιο κατάλογο με το αρχείο Circle.java, Rectangle.java, και Draw.java αρχεία προέλευσης (τα οποία αποθηκεύουν αντίστοιχα την καταχώριση 3, την καταχώριση 4 και την καταχώριση 5), συγκεντρώνουν αυτά τα αρχεία προέλευσης μέσω μιας από τις ακόλουθες γραμμές εντολών:

javac Draw.java javac * .java

Εκτελέστε το Σχεδιάζω εφαρμογή ως εξής:

κλήρωση java

Πρέπει να παρατηρήσετε την ακόλουθη έξοδο:

Κύκλος που σχεδιάστηκε στο (10.0, 20.0), με ακτίνα 15.0 και χρώμα 1 Κύκλος που σχεδιάστηκε στο (30.0, 20.0), με ακτίνα 10.0, και χρώμα 1 Ορθογώνιο σχεδιάστηκε με επάνω αριστερή γωνία στο (5,0, 8,0) και κάτω δεξιά γωνία στο (8.0, 9.0) και το χρώμα 1

Σημειώστε ότι θα μπορούσατε επίσης να δημιουργήσετε την ίδια έξοδο καθορίζοντας τα ακόλουθα κύριος() μέθοδος:

δημόσιο στατικό κενό (String [] args) {Circle c = new Circle (10, 20, 15); c.draw (Drawable.RED); c = νέος κύκλος (30, 20, 10); c.draw (Drawable.RED); Ορθογώνιο r = νέο ορθογώνιο (5, 8, 8, 9); r.draw (Drawable.RED); }

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

Προσοχή!