java:objects

Differences

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

Link to this comparison view

Next revision
Previous revision
Next revision Both sides next revision
java:objects [2015/01/22 08:30]
gthanos created
java:objects [2016/01/22 15:36]
gthanos [Πολλαπλοί κατασκευαστές σε μία κλάση]
Line 1: Line 1:
 ====== Δημιουργώντας Αντικείμενα ====== ====== Δημιουργώντας Αντικείμενα ======
  
-Μέχρι τώρα αναφέραμε ότι η κλάση είναι το βασικό σχέδιο μέσα από το οποίο δημιουργούνται επιμέρους αντικείμενα που φέρουν τα χαρακτηριστικά της κλάσης. Επίσης,​ δείξαμε πως ορίζουμε μία κλάση μέσα απο παραδείγματα,​ αλλά δεν δείξαμε πως δημιουργούμε αντικείμενα από τις κλάσεις που ορίσαμε. ​+Μέχρι τώρα αναφέραμε ​στην [[ oop:​introduction | "​Εισαγωγή στον Αντικειμενοστραφή Προγραμματισμό"​ ]] ότι η κλάση είναι το βασικό σχέδιο μέσα από το οποίο δημιουργούνται επιμέρους αντικείμενα που φέρουν τα χαρακτηριστικά της κλάσης. Επίσης,​ δείξαμε πως ορίζουμε μία κλάση μέσα από παραδείγματα,​ αλλά δεν δείξαμε πως δημιουργούμε αντικείμενα από τις κλάσεις που ορίσαμε. ​
  
-Παρακάτω δίνεται ένα πρόγραμμα που δημιουργεί συγκεκριμένα αντικείμενα και εκτυπώνει τα αποτελέσματα στην κονσόλα.+Παρακάτω δίνεται ένα πρόγραμμα που δημιουργεί συγκεκριμένα αντικείμενα ​του τύπου **Point** και **Rectangle** ​και εκτυπώνει τα αποτελέσματα στην κονσόλα.
  
 <code java Point.java>​ <code java Point.java>​
 public class Point { public class Point {
-   ​private int xCoord, yCoord+    private int x; 
-   ​ +    ​private int y
-   ​public Point(int ​x, int y) { +     
-       xCoord = x; +    public Point(int ​xPos, int yPos) { 
-       yCoord = y; +      = xPos
-   ​+      = yPos
-   ​public ​void setX(int x) { +    
-       xCoord = x; +     
-   ​+    ​public ​int getX() { 
-   ​public void setY(int y) { +      ​return ​x; 
-       yCoord ​y+    
-   ​+     
-   ​public int getX() { +    ​public void setX(int xPos) { 
-       ​return ​xCoord+      ​x ​xPos
-   ​+    
-   ​public ​int getY() { +     
-       return yCoord+    ​public int getY() { 
-   ​ +      return ​y
 +    
 +     
 +    ​public ​void setY(int yPos) { 
 +      y = yPos
 +    }
 } }
 </​code>​ </​code>​
Line 30: Line 35:
 <code java Rectangle.java>​ <code java Rectangle.java>​
 public class Rectangle { public class Rectangle {
-   private int widthheight; +     
-   ​private Point origin; +  // the Rectangle class has 3 fields 
-   ​ +  ​private int width
-   ​public Rectangle(Point p, int w, int h) { +  private int height; 
-       origin ​p+  private Point origin; 
-       width w+     
-       height ​h+  // the Rectangle class has one constructor 
-   ​+  ​public Rectangle(int ​setWidth, int setHeight, Point o) { 
-   ​ +    ​width ​setWidth
-   ​public Rectangle(int ​w, int h) { +    ​height ​setHeight
-       ​width = w+    ​origin ​o
-       ​height = h+  
-   ​+   
-   ​ +  public Rectangle(int ​setWidth, int setHeight) { 
-   ​public void setOrigin(Point p) { +    width = setWidth
-      ​origin ​p+    height = setHeight
-   ​+  
-   ​ +     
-   ​public ​void setHeight(int h) { +  // the Rectangel class has 3 methods 
-       height = h+  ​public void setWidth(int newWidth ​) { 
-   ​+    ​width ​newWidth
-   ​ +  
-   ​public void setWidth(int w) { +   
-       width w+  public int getWidth() { 
-   ​+    ​return width
-   ​ +  
-   ​public ​Point getOrigin() { +     
-       ​return ​origin+  public void setHeight(int newHeight ​) { 
-   ​+    ​height ​newHeight
-   ​ +  
-   ​public ​int getHeight() { +   
-       return height+  public ​int getHeight() { 
-   ​+    return ​height
-   ​ +  
-   ​public ​int getWidth() { +     
-       ​return ​width+  public ​void setOrigin(Point o) { 
-   ​+    ​origin = o
-   ​ +  
-   // Move rectangle origin by x,y +   
-   public ​void move(int x, int y) { +  public ​Point getOrigin() { 
-       origin.setX( origin.getX() + x )+    return ​origin
-       origin.setY( origin.getY() + y ) +  
-   }+   
 +  public ​int getArea() { 
 +       return width * height
 +  }
        
 +  // Move rectangle origin by x,y
 +  public void move(int dx, int dy) {
 +    origin.setX( origin.getX() + dx );
 +    origin.setY( origin.getY() + dy );
 +  }
 } }
 </​code>​ </​code>​
Line 84: Line 97:
         // Declare and create a point object and two rectangle objects.         // Declare and create a point object and two rectangle objects.
         Point originOne = new Point(23, 94);         Point originOne = new Point(23, 94);
-        Rectangle rectOne = new Rectangle(originOne, ​100, 200);+        Rectangle rectOne = new Rectangle(100,​ 200, originOne);
         Rectangle rectTwo = new Rectangle(50,​ 100);         Rectangle rectTwo = new Rectangle(50,​ 100);
   
Line 105: Line 118:
     }     }
 } }
 +</​code>​
 +
 +Για να μεταγλωτίσουμε τα παραπάνω πρόγραμμα αρκεί να γράψουμε
 +
 +<​code>​
 +javac Point.java
 +javac Rectange.java
 +javac CreateObjectDemo.java
 +</​code>​
 +
 +και για να το τρέξουμε γράφουμε
 +
 +<​code>​
 +java CreateObjectDemo
 </​code>​ </​code>​
  
Line 120: Line 147:
  
 Από τα πάραπάνω αξίζει να προσέξουμε τα εξής. Από τα πάραπάνω αξίζει να προσέξουμε τα εξής.
 +  - Εκτελούμε την κλάση η οποία περιέχει την μέθοδο **main** η οποία εκκινεί την εκτέλεση του προγράμματος <​code>​public static void main(String[] args) { .... } </​code>​
   - Η κλάση Rectangle έχει δύο κατασκευαστές οι οποίοι καλούνται εναλλάξ στη συνάρτηση **main** προκειμένου να αρχικοποιήσουν τα αντικείμενα (**objects**) ''​rectOne''​ και ''​rectTwo''​.   - Η κλάση Rectangle έχει δύο κατασκευαστές οι οποίοι καλούνται εναλλάξ στη συνάρτηση **main** προκειμένου να αρχικοποιήσουν τα αντικείμενα (**objects**) ''​rectOne''​ και ''​rectTwo''​.
   - H συνάρτηση ''​System.out.println()''​ εκτυπώνει ένα αλφαριθμητικό (string) ακολουθούμενο από χαρακτήρα αλλαγής γραμμής.   - H συνάρτηση ''​System.out.println()''​ εκτυπώνει ένα αλφαριθμητικό (string) ακολουθούμενο από χαρακτήρα αλλαγής γραμμής.
Line 142: Line 170:
 </​code>​ </​code>​
  
-Οι πρώτες δύο γραμμές ορίζουν τις μεταλητές ''​originOne'',​ ''​rectOne'',​ ''​rectTwo''​. Οι μεταβλητές δυνητικά δείχνουν σε τύπους δεδομένων Point, Rectange, Rectangle. Προς το παρόν όμως το περιεχόμενο των μεταβλητών αυτών είναι απροσδιόριστο (undefined). Σε αναλογία με την γλώσσα ​φανταστείτε τις μεταβλητές αυτές ως pointers που δεν είναι αρχικοποιημένοι σε κάποια υφιστάμενη διεύθυνση μνήμης. Η τιμή τους είναι απροσδιόριστη και η προσπάθεια να γράψουμε στη διεύθυνση μνήμης που δείχνουν θα προκαλάσει Segmentation Fault. Η παρακάτω εικόνα δείχνει την ύπαρξη ενός μη αρχικοποιημένου δείκτη.+Οι πρώτες δύο γραμμές ορίζουν τις μεταλητές ''​originOne'',​ ''​rectOne'',​ ''​rectTwo''​. Οι μεταβλητές δυνητικά δείχνουν σε τύπους δεδομένων Point, Rectange, Rectangle. Προς το παρόν όμως το περιεχόμενο των μεταβλητών αυτών είναι απροσδιόριστο (στην πραγματικότητα ο compiler αρχικοποεί τις μεταβλητές αυτές στην τιμή **null**).  
 + 
 +//__Σε αναλογία με την γλώσσα ​C__, φανταστείτε τις μεταβλητές αυτές ως pointers που δεν είναι αρχικοποιημένοι σε κάποια υφιστάμενη διεύθυνση μνήμης. Η τιμή τους είναι απροσδιόριστη και η προσπάθεια να γράψουμε στη διεύθυνση μνήμης που δείχνουν θα προκαλάσει Segmentation Fault.//  
 + 
 +Η παρακάτω εικόνα δείχνει την ύπαρξη ενός μη αρχικοποιημένου δείκτη.
  
 {{ :​java:​reference-variables-01.png |}} {{ :​java:​reference-variables-01.png |}}
Line 168: Line 200:
   - Αρχικοποίηση των εσωτερικών μεταβλητών (πεδίων) του αντικειμένου με κλήση του κατάλληλου κατασκευαστή της κλάσης. Εάν δεν έχει οριστεί κατασκευαστής τότε ο τελεστής new καλείται με χρήση του default κατασκευαστή (default constructor) που δεν έχει ορίσματα (π.χ. ''​MyObject obj = new MyObject();'',​ όπου για την κλάση ''​MyObject''​ δεν έχει οριστεί κανένας κατασκευατής).   - Αρχικοποίηση των εσωτερικών μεταβλητών (πεδίων) του αντικειμένου με κλήση του κατάλληλου κατασκευαστή της κλάσης. Εάν δεν έχει οριστεί κατασκευαστής τότε ο τελεστής new καλείται με χρήση του default κατασκευαστή (default constructor) που δεν έχει ορίσματα (π.χ. ''​MyObject obj = new MyObject();'',​ όπου για την κλάση ''​MyObject''​ δεν έχει οριστεί κανένας κατασκευατής).
  
-<WRAP tip>+<WRAP tip 80% center round>
 Κατά την χρήση **primitive** τύπων δεδομένων (int, float, double) δεν απαιτείται η χρήση του τελεστή **new** διότι η απαραίτητη μνήμη δεσμεύεται στο stack της μεθόδου που εκτελείται. ​ Κατά την χρήση **primitive** τύπων δεδομένων (int, float, double) δεν απαιτείται η χρήση του τελεστή **new** διότι η απαραίτητη μνήμη δεσμεύεται στο stack της μεθόδου που εκτελείται. ​
 </​WRAP>​ </​WRAP>​
Line 174: Line 206:
 ===== Πολλαπλοί κατασκευαστές σε μία κλάση ===== ===== Πολλαπλοί κατασκευαστές σε μία κλάση =====
  
-Μία κλάση μπορεί να έχει πολλούς διαφορετικούς. Κάθε κατασκευαστής ορίζει μία διαφορετική αρχικοποίηση των εσωτερικών μεταβλητών των αντικειμένων που δημιουργούντια με βάση το "​σχέδιο"​ της κλάσης. Το ποιός κατασκευαστής θα κληθεί εξαρτάται από τον τύπο, τη σειρά και τον αριθμό των ορισμάτων σε αναλογία με την υπερφόρτωση ​συναρτήσεων. Έτσι στη συνάρτηση main του παραδείγματος μας καλούνται δύο διαφορετικοί κατασκευαστές για δύο διαφορετικά αντικείμενα της ίδιας κλάσης.+Μία κλάση μπορεί να έχει πολλούς διαφορετικούς. Κάθε κατασκευαστής ορίζει μία διαφορετική αρχικοποίηση των εσωτερικών μεταβλητών των αντικειμένων που δημιουργούντια με βάση το "​σχέδιο"​ της κλάσης. Το ποιός κατασκευαστής θα κληθεί εξαρτάται από τον τύπο, τη σειρά και τον αριθμό των ορισμάτων σε αναλογία με την υπερφόρτωση ​μεθόδων. Έτσι στη συνάρτηση ​**main** του παραδείγματος μας καλούνται δύο διαφορετικοί κατασκευαστές για δύο διαφορετικά αντικείμενα της ίδιας κλάσης.
  
 <code java> <code java>
Line 195: Line 227:
 </​code>​ </​code>​
  
-<WRAP important>​+<WRAP important ​80% center round>
 Απαραίτητη προϋπόθεση για να δουλέψει ο παραπάνω κώδικας είναι το πεδίο speed να είναι προσβάσιμο,​ δηλαδή να μην έχει προσδιοριστή τύπου **private**. Απαραίτητη προϋπόθεση για να δουλέψει ο παραπάνω κώδικας είναι το πεδίο speed να είναι προσβάσιμο,​ δηλαδή να μην έχει προσδιοριστή τύπου **private**.
 </​WRAP>​ </​WRAP>​
  
-<WRAP tip> +<WRAP tip 80% center round
-Όπως προείπαμε μία καλή προγραμματιστική πρακτική είναι η απόκρυψη των πεδίων κάθε κλάσης και η δήλωση συναρτήσεων για την πρόσβαση στα δεδομένα της. Σε αυτή την περίπτωση η πρόσβαση στα πεδία των αντικειμένων είναι μη επιτρεπτή (ο compiler δεν μεταγλωττίζει το πρόγραμμα).+Όπως προείπαμε μία καλή προγραμματιστική πρακτική είναι η απόκρυψη των πεδίων κάθε κλάσης και η δήλωση συναρτήσεων για την πρόσβαση στα δεδομένα της. Σε αυτή την περίπτωση η απευθείας ​πρόσβαση στα πεδία των αντικειμένων είναι μη επιτρεπτή (ο compiler δεν μεταγλωττίζει το πρόγραμμα). Η πρόσβαση σε μεταβλητές που έχουν τον προσδιοριστή **private** μπορεί να γίνει μόνο μέσω βοηθητικών συναρτήσεων (set/get) που έχουν το προσδιοριστή **public**.
 </​WRAP>​ </​WRAP>​
  
Line 213: Line 245:
 </​code>​ </​code>​
  
-<WRAP important>​+<WRAP important ​80% center round>
 Ισχύουν και για τις μεθόδους όσα αναφέρονται για τους προσδιοριστές τύπου **public**, **private** των πεδίων. Ισχύουν και για τις μεθόδους όσα αναφέρονται για τους προσδιοριστές τύπου **public**, **private** των πεδίων.
 </​WRAP>​ </​WRAP>​
Line 219: Line 251:
 ===== Garbage Collection ===== ===== Garbage Collection =====
  
-Οι γλώσσες υψηλού επιπέδου που μέχρι τώρα έχετε γνωρίσει (**C**) αναθέτους την ευθύνη δέσμευση μνήμης στον προγραμματιστή μέσω των συναρτήσεων **malloc()** και **free()**. Σε αντιδιαστολή,​ η **JAVA** αφήνει τον προγραμματιστεί να ορίσει όσα αντικείμενα επιθυμεί και δεσμεύει την μνήμη για αυτά μέσω του τελεστή **new**.+Οι γλώσσες υψηλού επιπέδου που μέχρι τώρα έχετε γνωρίσει (**C**) αναθέτουν την ευθύνη δέσμευση μνήμης στον προγραμματιστή μέσω των συναρτήσεων **malloc()** και **free()**. Σε αντιδιαστολή,​ η **JAVA** αφήνει τον προγραμματιστεί να ορίσει όσα αντικείμενα επιθυμεί και δεσμεύει την μνήμη για αυτά μέσω του τελεστή **new**
 + 
 +Πως όμως αποδεσμεύεται η μνήμη που δεσμεύτηκε προηγούμενα από το πρόγραμμα μας, αλλά δεν την χρειαζόμαστε πλέον; Αν η μνήμη δεν αποδεσμεύεται και το πρόγραμμα μας τρέξει για αρκετή ώρα δεσμεύοντας μνήμη, τότε είναι σίγουρο ότι θα το τερματίσει το λειτουργικό σύστημα. Η απάντηση,​ όσον αφορά την αποδέσμευση μνήμης στη Java δίνεται παρακάτω.
  
-Περιοδικά το **JVM** κοιτάει εάν υπάρχουν αντικείμενα ​για ​τα οποία δεν υπάρχουν πλέον μεταβλητές που δείχνουν σε αυτά. Σε αυτές τις περιπτώσεις ελευθερώνει την μνήμη που έχει δεσμευτεί για τα αντικείμενα που εντόπισε. Ο μηχανισμός αυτός ονομάζεται **Garbage Collection** και απαντάται σε αρκετές γλώσσες υψηλού επιπέδου απελευθερώνοντας τον προγραμματιστή από την ευθύνη αποδέσμευσης της μνήμης που δεσμέυτηκε.+Περιοδικά το **JVM** κοιτάει εάν υπάρχει δεσμευμένη μνήμη για ​αντικείμενα ​στα οποία δεν υφίστανται ​πλέον μεταβλητές που δείχνουν σε αυτά. Σε αυτές τις περιπτώσειςελευθερώνεται η μνήμη που έχει δεσμευτεί για τα αντικείμενα που εντόπισε ​το JVM. Ο μηχανισμός αυτός ονομάζεται **Garbage Collection** και απαντάται σε αρκετές γλώσσες υψηλού επιπέδου απελευθερώνοντας τον προγραμματιστή από την ευθύνη αποδέσμευσης της μνήμης που δεσμεύτηκε ​προηγούμενα.
  
-Περισσότερα για την λειτουργία του Garbage Collector μπορείτε να βρείτε [[http://​www.oracle.com/​webfolder/​technetwork/​tutorials/​obe/​java/​gc01/​index.html|εδώ]].+Η ευθύνη της αποδέσμευσης μνήμης επαφίεται στο Garbage Collector, πράγμα που κάνει πιο εύκολη τη ζωή του προγραμματιστή. Από την άλλη, σε προγράμματα που απαιτούν πολύ υψηλές επιδόσεις ή έχουν ​αυστηρούς περιορισμούς ως προς τον χρόνο εκτέλεσης ​τους, ο αλγόριθμος που χρησιμοποιεί ο Garbage Collector μπορεί να εισάγει μη αποδεκτή καθυστέρηση.
  
 +Περισσότερα για την λειτουργία του Garbage Collector και τις εναλλακτικές υλοποιήσεις μπορείτε να βρείτε [[http://​www.oracle.com/​webfolder/​technetwork/​tutorials/​obe/​java/​gc01/​index.html|εδώ]].
  
-|Προηγούμενο:​ [[:​java:​class_methods | Μέθοδοι της Κλάσης ]] | Επόμενο:​ [[:​java:​this_operator | Oι τελεστές this και super ]]|+|Προηγούμενο:​ [[:​java:​class_methods | Μέθοδοι της Κλάσης ]] | Επόμενο:​ [[:​java:​this_operator | O τελεστής this ]]|
  
  
java/objects.txt · Last modified: 2018/02/16 16:03 by gthanos