java:interfaces

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Last revision Both sides next revision
java:interfaces [2016/04/09 06:48]
gthanos [Χρησιμοποιώντας ένα interface ως τύπο δεδομένων]
java:interfaces [2017/02/16 14:21]
gthanos
Line 1: Line 1:
-====== Διεπαφές (Interfaces) ======+====== Διεπαφή (Interface) ======
  
 ===== Εισαγωγικά ===== ===== Εισαγωγικά =====
  
-Κατά την ανάπτυξη προγραμμάτων είναι σημαντικό να είναι τυποποιημένος ο τρόπος αλληλεπίδρασης ανάμεσα σε διαφορετικά συστήματα. Η ύπαρξη ενός "​συμβολαίου"​ το οποίο καθορίζει ακριβώς το πώς μπορεί μια εφαρμογή ​να αλληλεπιδράσει με μια άλλη διευκολύνει την ανεξάρτητη ανάπτυξη κώδικα από διαφορετικές ομάδες.+Κατά την ανάπτυξη προγραμμάτων είναι σημαντικό να είναι τυποποιημένος ο τρόπος αλληλεπίδρασης ανάμεσα σε διαφορετικά συστήματα. Η ύπαρξη ενός "​συμβολαίου"​ το οποίο καθορίζει ακριβώς το πώς μπορεί μία κλάση ​να αλληλεπιδράσει με μια άλλη διευκολύνει την ανεξάρτητη ανάπτυξη κώδικα από διαφορετικούς προγραμματιστές.
  
 Υπακούοντας στην παραπάνω αρχή, η Java εισάγει την έννοια της διεπαφής (**interface**). Τα //​interfaces//​ στη Java λειτουργούν ως προ-συμφωνημένες διεπαφές μεταξύ προγραμματιστών. Κάθε interface τυπικά σχετίζεται με: Υπακούοντας στην παραπάνω αρχή, η Java εισάγει την έννοια της διεπαφής (**interface**). Τα //​interfaces//​ στη Java λειτουργούν ως προ-συμφωνημένες διεπαφές μεταξύ προγραμματιστών. Κάθε interface τυπικά σχετίζεται με:
 +  - **τους προγραμματιστές που το χρησιμοποιούν:​** οι προγραμματιστές γράφουν την εφαρμογή τους ώστε να χρησιμοποιεί τις μεθόδους του //​interface//,​ οι οποίες παρέχουν τη λειτουργικότητα που υποδεικνύει το //​interface//​ αυτό.
 +  - **τους προγραμματιστές που το υλοποιούν:​** εφόσον θέλουν να ενσωματώσουν τη λειτουργικότητα που υποδεικνύει το //​interface//​ σε συγκεκριμένες κλάσεις θα πρέπει να υλοποιήσουν τις μεθόδους του στις ​ κλάσεις αυτές.
  
-  - τους προγραμματιστές που το χρησιμοποιούν ​και  +Από τα παραπάνω εξάγεται ότι το //​interface//​ είναι μία προσυμφωνημένη διεπαφή η οποία δεσμεύει και τις δύο πλευρές,​ τόσο ​τους προγραμματιστές που το υλοποιούν,​ όσο και εκείνους που το χρησιμοποιούν. Παρακάτω θα δούμε την ​υποστήριξη των interfaces ​από τον compiler της Java και τους κανόνες που τα διέπουν.
-  - τους προγραμματιστές που το υλοποιούν. +
  
-Οι πρώτοι γράφουν την εφαρμογή τους ώστε να χρησιμοποιεί τις μεθόδους ​του interface για να παρέχει συγκεκριμένη ​λειτουργικότητα. ​+Ως παράδειγμα, θεωρήστε ένα //​interface//​ το οποίο ορίζει ​τη χρήση ​ενός χρονόμετρου (//​Timer//​). Όσοι επιθυμούν ​να υλοποιήσουν το χρονόμετρο θα πρέπει κατ' ​ελάχιστο να υλοποιήσουν ​τις ​παρακάτω ​μεθόδους
 +  * **setTimer:​** ​αρχικοποίηση του timer  
 +  * **startTimer:​** ​έναρξη του ​timer και  
 +  * **endTimer:​** τερματισμός του timer
  
-Οι δεύτεροι, αν θέλουν να επωφεληθούν ​από την λειτουργικότητα που υποδεικνύει ένα //​interface// ​ θα πρέπει να υλοποιήσουν τις ​μεθόδους του στα προγράμματά τους και να επιλέγουν προς ​χρήση κλάσεις που υλοποιούν το συγκεκριμένο interface. ​+Ας υποθέσουμε τώρα ότι ένας κατασκευαστής ηλεκτρικών συσκευών (κλιμαστιστικά, ψυγεία κ.α.) χρησιμοποιεί Java για τον αυτοματισμό τους και θέλει να χρησιμοποιεί μία κλάση τύπου //Timer// για ​τις ​συσκευές που κατασκευάζει ​προκειμένου να ενσωματώσει τη λειτουργία του χρονόμετρου. Για να το κάνει αυτό, μπορεί να χρησιμοποιήσει __οποιαδήποτε κλάση είναι σύμφωνη με τον παραπάνω //​interface//​__. Ας υποθέσουμε επίσης ότι υπάρχουν τουλάχιστον δύο διαφορετικές ​κλάσεις που υλοποιούν το συγκεκριμένο interface ​//Timer//
  
-Από τα παραπάνω εξάγεται ότι ​το interface ​είναι μία προσυμφωνημένη διεπαφή η οποία δεσμεύει και τις δύο πλευρέςδηλαδή οι χρήστες του δεσμεύονται να χρησιμοποιούν τις μεθόδους ​του //​interface// ​και οι προγραμματιστές που το υλοποιούν να το υλοποιούν ​στις κλάσεις τους. Παρακάτω θα δούμε την υποστήριξη των interfaces ​από τον ​compiler της Java και τους κανόνες που ​τα διέπουν.+Γνωρίζοντας ότι ​όλες ​οι εναλλακτικές κλάσεις ​που ​θα χρησιμοποιήσει θα υλοποιούν υποχρεωτικά το συγκεκριμένο //​interface//​, αρκεί να σχεδιάσει και να υλοποιήσει το λογισμικό του του ώστε ​να χρησιμοποιεί το //​interface//​ αυτό. Σε αυτή την περίπτωση, σχεδιάζει και γράφει ​το λογισμικό ​με γνώμονα τον ​interface ​και όχι τη συγκεκριμένη κλάση ​που ​θα επιλέξει να χρησιμοποιήσει τελικά.
  
-Ως παράδειγμα, ​θεωρήστε ένα interface ​το οποίο ορίζει πως όποιοι κατασκευαστές συσκευών θέλουν να χρησιμοποιήσουν χρονόμετρο σε συσκευή τους πρέπει να υλοποιήσουν ​τις μεθόδους setTimer, startTimer και endTimer.  +Υιοθετώντας την έννοια του //​interface//​ και γράφοντας κώδικα που χρησιμοποιεί //​interfaces//,​ γράφουμε κώδικα που ​είναι ανεξάρτητος από την οποιαδήποτε υλοποίηση των //​interfaces//​ που χρησιμοποιεί. Γενικότερα, ισχύει η αρχή ότι οι υλοποιήσεις ενός interface μπορεί να αλλάξουν, τα interfaces ​όμως συνιστάται ​να παραμένουν σταθερά.
-Ένας κατασκευαστής κλιματιστικών (που θέλει να μπορεί να σταματήσει ​η λειτουργία της συσκευής ​μετά από ένα χρονικό ​διάστημα)και ένας κατασκευαστής κουζινών (που θέλει η κουζίνα του να παράγει έναν ​ήχο μετά από ένα χρονικό διάστημα) επιλέγουν να υλοποιήσουν αυτές τις μεθόδους. Με αυτόν το τρόπο τηρούν ένα συμβόλαιο αλληλεπίδρασης ​με το χρονόμετρο.+
  
-Οι υλοποιήσεις για τις κουζίνες και τα κλιματιστικά είναι εντελώς ​διαφορετικές και γίνονται ανεξάρτητα η μία από την άλλη. Η εγγύηση είναι μόνο ότι οι μέθοδοι έχουν υλοποιηθεί και παρέχουν ασφαλή και ομοιόμορφο τρόπο αλληλεπίδρασης με τα χρονόμετρα των συσκευών.  +Οποιοσδήποτε προγραμματιστής χρησιμοποιεί το παραπάνω //interface// δεν ​χρειάζεται να γνωρίζει το παραμικρό για την εσωτερική υλοποίηση των κλάσεων που το υλοποιούν. ​Η επιλογή της κλάσης που το υλοποιεί μπορεί να μεταβάλλεται ​χωρίς να επηρεάζεται ο κώδικας που το χρησιμοποιεί.
- +
-Ένας χρήστης αυτών των συσκευών δε χρειάζεται να γνωρίζει ​πώς ακριβώς λειτουργούν εσωτερικά τα χρονόμετρα, αλλά του αρκεί να γνωρίζει ότι ​μπορεί να αλληλεπιδράσει με το χρονόμετρο οποιασδήποτε τέτοιας συσκευής μέσω ίδιων πάντα μεθόδων οι οποίες παίρνουν πάντα συγκεκριμένες παραμέτρους κι επιστρέφουν συγκεκριμένη τιμή.  +
- +
-Αντιπαραθέστε μια κατάσταση όπου οι συσκευές δεν τηρούν αυτό το συμβόλαιο (δηλαδή δεν υλοποιούν το συγκεκριμένο interface) και ως αποτέλεσμα ο χρήστης αναγκάζεται να χρησιμοποιήσει μια μέθοδο setACTimer για το χρονόμετρο του κλιματιστικού,​ μια μέθοδο setStoveTimer για το χρονόμετρο της κουζίνας κτλ.  +
- +
-===== Ορίζοντας ένα Interface ===== +
- +
-Ένα interface ορίζεται με τρόπο παρόμοιο με κλάση, αλλά με το χαρακτηρισμό interface, για παράδειγμα,​  +
- +
-<code java> +
-public interface ApplianceTimer{ +
- +
-    // constant declarations ​    +
-    int TIMEOUT = 20000; +
-  +
-    // method signatures +
-    public int setTimer(int t); +
-    public int startTimer(int t); +
-    public int stopTimer();​ +
-+
-</​code>​ +
- +
-Ο προσδιοριστής ενός interface είναι public ή μπορούμε να τον παραλείψουμε (package-private). +
- +
-Ένα interface μπορεί να περιέχει **μόνο** σταθερές (πχ. το TIMΕOUT στο παράδειγμα),​ abstract μεθόδους,​ default μεθόδους,​ static μεθόδους. Θα εξηγήσουμε κάθε μία από τις κατηγορίες μεθόδων παρακάτω. Όλες οι μέθοδοι σε ένα interface είναι εξ ορισμού ​//public//, κατά συνέπεια ο προσδιοριστής public σε αυτές μπορεί ​να παραληφθεί. +
- +
-Τόσο στις κλάσεις όσο και στα interfaces ορίζεται ​η ιδιότητα της κληρονομικότητας. Η διαφορά είναι ότι ενώ στην κλάση μπορούμε να έχουμε μόνο μία γονική κλάση, στα interfaces μπορούμε να έχουμε περισσότερα του ενός γονικά interfaces. +
- +
- +
-===== Υλοποιώντας ένα Interface ===== +
- +
-Θα δείξουμε την υλοποίηση ενός interface μέσα από ένα παράδειγμα. +
- +
-Μια πολύ συνηθισμένη χρήση interfaces είναι για το χαρακτηρισμό αντικειμένων τα οποία μπορούν να συγκριθούν μεταξύ τους:  +
- +
-Η μέθοδος ''​Arrays.Sort''​ μπορεί να ταξινομήσει τα περιεχόμενα ενός πίνακα που αποτελείται από οποιοδήποτε είδος αντικειμένων αλλά μόνο υπό την προϋπόθεση ότι η κλάση που ​αναπαριστά αυτά τα αντικείμενα υλοποιεί το interface Comparable:​ +
-<code java> +
-public interface Comparable +
-+
-     int compareTo(Object other); +
-+
-</​code>​ +
- +
-Μια ​κλάση που υλοποιεί το Comparable πρέπει να υλοποιήσει τη μέθοδο ''​compareTo''​. Εφόσον συμβεί αυτό, η μέθοδος Arrays.Sort μπορεί πια να αλληλεπιδράσει με τα αντικείμενα που θέλουμε να ταξινομήσουμε ώστε να μας παρέχει την υπηρεσία ταξινόμησης.  +
- +
-Ας δούμε ένα παράδειγμα πάνω στην κλάση Rectangle που έχουμε ορίσει σε προηγούμενες ενότητες. Σύμφωνα με το documentation του interface Comparable ​η compareTo πρέπει ​να επιστρέφει ακέραιο αρνητικό,​ μηδέν ή θετικό αν το τρέχον αντικείμενο (this) θεωρείται αντίστοιχα "​μικρότερο", "​ίσο" ​ ή "​μεγαλύτερο"​ από αυτό με το οποίο το συγκρίνουμε. Το πώς ορίζεται το "μικρότερο",​ κτλ. για αντικείμενα Rectangle είναι απόφαση του προγραμματιστή που ​υλοποιεί την κλάση Rectangle. Στο συγκεκριμένο παράδειγμα αποφασίζουμε να συγκρίνουμε τα αντικείμενα με βάση το εμβαδό τους. +
- +
-<code java Rectangle.java>​ +
-import java.util.Arrays;​ +
- +
-public class Rectangle implements Comparable { +
-    private int width = 0; +
-    private int height = 0; +
-    private Point origin; +
- +
-    public Rectangle() { +
-        origin = new Point(0, 0); +
-    } +
-    public Rectangle(Point p) { +
-        origin = p; +
-    } +
-    public Rectangle(int w, int h) { +
-        origin = new Point(0, 0); +
-        width = w; +
-        height = h; +
-    } +
-    public Rectangle(Point p, int w, int h) { +
-        origin = p; +
-        width = w; +
-        height = h; +
-    } +
- +
-    public void move(int x, int y) { +
-        origin.setX(x);​ +
-        origin.setY(y);​ +
-    } +
- +
-    public int getArea() { +
-        return width * height; +
-    } +
-     +
-    @Override +
-    public int compareTo(Object other) { +
-        Rectangle otherRect = (Rectangle) other; // απαραίτητο για να μπορεί να κληθεί η getArea  +
-        return this.getArea() - otherRect.getArea(); ​             +
-    } +
-     +
-    @Override String toString() { +
-        return origin + ", [" + width + " X " + height + "​]";​ +
-    } +
-     +
-    public static void main(String args[]) { +
-        Rectangle [] shapes = new Rectangle[4]; ​                                     +
-        shapes[0] = new Rectangle(4,​ 5);                                             +
-        shapes[1] = new Rectangle(1,​ 8);                                             +
-        shapes[2] = new Rectangle(2,​ 15);                                            +
-        shapes[3] = new Rectangle(9,​ 2);                                             +
-                                                                                 +
-        System.out.println("​Initial array:"​); ​                                       +
-        for (Rectangle rectangle : shapes) {                                         +
-            System.out.println(rectangle + ", area: " + rectangle.getArea()); ​       +
-        }                                                                            +
-                                                                                 +
-        Arrays.sort(shapes); ​                                                        +
-                                                                                 +
-        System.out.println("​Sorted array:"​); ​                                        +
-        for (Rectangle rectangle : shapes) {                                         +
-            System.out.println(rectangle + ", area: " + rectangle.getArea()); ​       +
-        }  +
-    } +
-+
-</​code>​ +
- +
- +
-Για να εκτελέσετε το παράδειγμα κατεβάστε την κλάση ''​Point'',​ από [[:​java:​objects |εδώ]]. +
- +
-===== Χρησιμοποιώντας ένα interface ως τύπο δεδομένων ===== +
- +
-Μπορείτε να χρησιμοποιήσετε ένα Java Interface ως ένα reference τύπο δεδομένων. Μπορείτε να χρησιμοποιήσετε το όνομα ενός interface ως τον τύπο μιας παραμέτρου σε μία Java μέθοδο ή τύπο μιας τοπικής μεταβλητής στο σώμα μίας μεθόδου. Προϋπόθεση είναι οι τιμές των μεταβλητών να δείχνουν σε αντικείμενα των οποίων οι κλάσεις ​υλοποιούν ​το συγκεκριμένο interfaceΔείτε το παρακάτω παράδειγμα. +
- +
-Αρχικά ορίζουμε ένα interface με όνομα MyComparable το οποίο ορίζει τη μέθοδο isLarger που επιστρέφει true ή false ανάλογα με το αν το τρέχον αντικείμενο είναι μεγαλύτερο ​ή μικρότερο ​της ​παραμέτρου :  +
- +
-<code java MyComparable.java>​  +
-public interface MyComparable { +
-  public boolean isLarger(MyComparable other); +
-+
-</​code>​ +
- +
-Γράφουμε την Rectangle ώστε να υλοποιεί και το νέο μας interface:​ +
-<code java Rectangle.java>​ +
-public class Rectangle implements MyComparable{ +
-     +
-  // the Rectangle class has 3 fields +
-  private int width; +
-  private int height; +
-  private Point origin; +
-     +
-  // the Rectangle class has one constructor +
-  public Rectangle(int initWidth, int initHeight, Point initOrigin) { +
-    width = initWidth;​ +
-    height = initHeight;​ +
-    origin = initOrigin;​ +
-  } +
-   +
-  public Rectangle(int initWidth, int initHeight, int xPos, int yPos) { +
-    this(initWidth,​ initHeight, new Point(xPos,​yPos));​ +
-  } +
-   +
-  public Rectangle(int initWidth, int initHeight) { +
-    this(initWidth,​ initHeight, 0, 0); +
-  } +
- +
-  public void setWidth(int newWidth ) { +
-    width = newWidth; +
-  } +
-   +
-  public int getWidth() { return width; } +
-     +
-  public void setHeight(int newHeight ) { +
-    height = newHeight;​ +
-  } +
-   +
-  public int getHeight() { return height; } +
-     +
-  public void setOrigin(Point newOrigin) { +
-    origin = newOrigin;​ +
-  } +
-   +
-  public Point getOrigin() { return origin; } +
-    +
-  @Override +
-  public boolean isLarger(MyComparable other) { +
-   Rectangle otherRect = (Rectangle) other; +
-    return (this.getArea() > otherRect.getArea());​ +
-  } +
-  +
-  @Override +
-  public String toString() { +
-    return origin + ", Dimensions [" + width + " X " + height + "​]";​ +
-  } +
-  +
-  public int getArea() { +
-       ​return width * height; +
-  } +
-}  +
-</​code>​ +
- +
-Τώρα, μπορούμε να ορίσουμε την ​κλάση ​''​TwosComparator''​ η οποία παρέχει μεθόδους που ​μπορούν να χρησιμοποιηθούν για σύγκριση ανάμεσα σε οποιαδήποτε δύο αντικείμενα //​εφόσον//​ αυτά ​υλοποιούν το MyComparable.  +
- +
-<code java TwosComparator.java>​ +
-public class TwosComparator { +
-     +
-    public MyComparable findLarger(MyComparable object1, MyComparable object2) { +
-        if (object1.isLarger(object2)) +
-            return object1; +
-        else  +
-            return object2; +
-    } +
-     +
-    public MyComparable findSmaller(MyComparable object1, MyComparable object2) { +
-        if (!(object1.isLarger(object2))) +
-            return object1; +
-        else  +
-            return object2; +
-    } +
-+
-</​code>​ +
- +
-Χρησιμοποιούμε την TwosComparator ως εξής:  +
-<code java Main.java>​ +
-public class Main { +
-       +
-    public static void main(String args[]) { +
-        Rectangle rec1 = new Rectangle(30,​ 40); +
-        Rectangle rec2 = new Rectangle(10,​ 50); +
-        TwosComparator comp = new TwosComparator();​ +
-      +
-        System.out.println("​rec1 is " + rec1); +
-        System.out.println("​rec2 is " + rec2); +
-      +
-        System.out.println( comp.findLarger(rec1,​ rec2) + " ​ is larger!"​);​ +
-        System.out.println( comp.findSmaller(rec1,​ rec2) + " ​ is smaller!"​);​ +
-    } +
-+
-</​code>​ +
- +
-===== Μεταβάλλοντας ένα υφιστάμενο Interface ===== +
- +
-Κάποιες φορές στον προγραμματισμό ​εμφανίζεται η ανάγκη ​να μεταβάλλουμε ένα υφιστάμενο interface ή να το επεκτείνουμε. Το πρόβλημα σε αυτές τις περιπτώσεις είναι ότι οι κλάσεις που υλοποιούν το συγκεκριμένο interface με την προσθήκη ή αλλαγή των υφιστάμενων μεθόδων θα πάψουν να το υλοποιούν. Επομένως μία μονομερής αλλαγή του interface δεν είναι εφικτή. Παρόλα αυτά υπάρχουν δύο εναλλακτικές που μπορούν ​να μας καλύψουν. +
- +
-  +
-**1η εναλλακτική:​** Να υλοποιήσουμε ένα νέο interface με παραπλήσιο όνομα, το οποίο να αποτελέσει τη νέα έκδοση του υφιστάμενου interface. +
-<code java> +
-public interface DoIt { +
-  +
-   void doSomething(int i, double x); +
-   int doSomethingElse(String s); +
-+
- +
-public interface DoItPlus extends DoIt { +
- +
-   ​boolean didItWork(int i, double x, String s); +
-    +
-+
-</​code>​ +
- +
-**2η εναλλακτική:​** Να υλοποιήσουμε μία ή περισσότερες //default// μέθοδους (όσες είναι και οι αλλαγές ή οι προσθήκες) μέσα στο υφιστάμενο interface, ώστε ακόμη και εάν ​οι κλάσεις που υλοποιούν το συγκεκριμένο interface δεν υλοποιούν τις νέες μεθόδους,​ οι υλοποιήσεις στις κλάσεις αυτές να γίνονται από το ίδιο το interface. +
-<code java> +
-public interface DoIt { +
- +
-   void doSomething(int i, double x); +
-   int doSomethingElse(String s); +
-   ​default boolean didItWork(int i, double x, String s) { +
-       // Method body  +
-   ​} ​  +
-+
-</​code>​ +
- +
-===== Default μέθοδοι ===== +
- +
-<WRAP 80% important center round> +
-**__Παρατήρηση:​__** Οι **default** μέθοδοι στην Java υλοποιούνται στην έκδοση 8 της γλώσσας. Μεταγλωττιστές που ανήκουν σε προηγούμενες εκδόσεις αδυνατούν να μεταγλωττίσουν τον παρακάτω κώδικά. +
-</​WRAP>​ +
- +
-Ας θεωρήσουμε το παρακάτω υποθετικό interface +
- +
-<code java StringInverter.java>​ +
-    public interface StringInverter { +
-        /** inverts a string +
-         */ +
-        String invert(String str); +
-    } +
-</​code>​ +
- +
-Ας υποθέσουμε τώρα ότι η κλάση MyString υλοποιεί το παραπάνω interface. +
- +
-<code java MyString.java>​ +
-import java.lang.*;​ +
-public class MyString implements StringInverter { +
-    String invert(String str) { +
-        StringBuffer strb = new StringBuffer(str);​ +
-        return strb.reverse().toString();​ +
-    } +
-+
-</​code>​ +
- +
-Αν υποθέσουμε ότι το αρχικό interface αλλάζει στο παρακάτω +
- +
-<code java StringInverter.java>​ +
-    public interface StringInverter { +
-        /** inverts a string +
-         */ +
-        String invert(String str); +
-        /** splits a string in half and inverts +
-         * the two parts. +
-         */ +
-        String invertHalf(String str); +
-    } +
-</​code>​ +
- +
-Τώρα ​η κλάση MyString δεν υλοποιεί πλέον το αρχικό interface. Αυτό ​μπορεί να συνεχίσει να υλοποιείται εάν η νέα μέθοδος έχει μία default υλοποίηση μέσα στο interface όπως παρακάτω. +
- +
-<code java StringInverter.java>​ +
-    public interface StringInverter { +
-        /* inverts a string +
-         */ +
-        String invert(String str); +
-        /* splits a string in half and inverts +
-         * the two parts +
-         */ +
-        default String invertHalf(String str) { +
-           int len = str.length();​ +
-           ​String str1 = str.substring(0,​ len/2); +
-           ​String str2 = str.substring(len/​2,​ len); +
-           ​return str2+str1;​ +
-        } +
-    } +
-</​code>​ +
- +
- +
- +
-===== Στατικές μέθοδοι ===== +
- +
-Εκτός από //default// μεθόδους ένα interface μπορεί να περιέχει και στατικές (//​static//​) μεθόδους. Οι στατικές μέθοδοι ορίζονται σε αναλογία με τις στατικές μεθόδους των κλάσεων και ουσιαστικά ανήκουν στις κλάσεις που θα υλοποιήσουν το interface και όχι στα αντικείμενα. Ένα παράδειγμα μπορείτε να δείτε παρακάτω. +
- +
-<code java StringInverter.java>​ +
-    public interface StringInverter { +
-        /** inverts a string +
-         */ +
-        String invert(String str); +
-        /** splits a string in half and inverts +
-         * the two parts +
-         */ +
-        default String invertHalf(String str) { +
-           int len = str.length();​ +
-           ​String str1 = str.substring(0,​ len/2); +
-           ​String str2 = str.substring(len/​2,​ len); +
-           ​return str2+str1;​ +
-        } +
-         +
-        /** removes character at index from String str +
-         * and returns the new String. +
-         */ +
-        static String removeChar(String str, int index) { +
-            if( str.length()-1 < index ) { +
-                return str; +
-            } +
-            String str1 = str.substring(0,​index);​ +
-            String str2; +
-            if( str.length() >= index-1 ) { +
-                str2 = new String(""​);​ +
-            } +
-            else { +
-                str2 = str.substring(index+1);​ +
-            } +
-            return str1+str2;​ +
-         +
-        } +
-    } +
-</​code>​ +
- +
-<WRAP 80% important center round> +
-**__Παρατήρηση:​__** Οι **static** μέθοδοι στην Java υλοποιούνται στην έκδοση 8 της γλώσσας. Μεταγλωττιστές που ανήκουν σε προηγούμενες εκδόσεις αδυνατούν να μεταγλωττίσουν τον παραπάνω κώδικά. +
-</​WRAP>​ +
- +
- +
-| Προηγούμενο : [[ :​java:​abstract_classes | Abstract Κλάσεις ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο:​ [[ :​java:​access_modifiers | Περιοριστές πρόσβασης ]]  |+
  
 +Αντιπαραθέστε τώρα την εναλλακτική μη ύπαρξης προσυμφωνημένων διεπαφών. Σε αυτή την περίπτωση κάθε πρόγραμμα ή ο κάθε κατασκευαστής θα έπρεπε να υλοποιεί την δική του κλάση για το χρονόμετρο,​ χωρίς να υπάρχει η δυνατότητα εύκολης χρήσης λογισμικού που προέρχεται από τρίτους. ​
  
 +Η προτυποποίηση που παρέχει ο μηχανισμός του //​interface//​ είναι αυτή που επιτρέπει:​
 +  - την εύκολη και χωρίς σφάλματα επαναχρησιμοποίηση κώδικα σε διαφορετικά προγράμματα και ​
 +  - την αλλαγή της υφιστάμενης υλοποίησης μιας κλάσης που υλοποιεί ένα //​interface//,​ δίχως οι χρήστες του //​interface//​ να έχουν γνώση για τις αλλαγές αυτές.
  
 +| Προηγούμενο : [[ :​java:​abstract_classes | Abstract Κλάσεις ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο:​ [[ :​java:​interface_definition | Δήλωση του interface ]]  |
java/interfaces.txt · Last modified: 2017/02/16 14:26 by gthanos