User Tools

Site Tools


java:type_casting

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
java:type_casting [2016/02/15 05:38] – [Κριτήρια χρήσης της κληρονομικότητας ως εργαλείο ανάπτυξης λογισμικού] gthanosjava:type_casting [Unknown date] (current) – external edit (Unknown date) 127.0.0.1
Line 4: Line 4:
  
 <code java> <code java>
-MountainBike myBike = new MountainBike();+Rectangle r1 = new Rectangle(100,100,5,-5);
 </code> </code>
  
-Από την παραπάνω δήλωση η μεταβλητή ''myBike'' είναι τύπου ''MountainBike''. Επειδή όμως ο τύπος ''MountainBike'' κληρονομεί από την μεταβλητή ''Bicycle'' **__η συγκεκριμένη μεταβλητή είναι και τύπου Bicycle__**. Επομένως, θα μπορούσαμε να γράψουμε+Από την παραπάνω δήλωση η μεταβλητή ''r1'' είναι τύπου ''Rectangle''. Επειδή όμως ο τύπος ''Rectangle'' κληρονομεί την κλάση ''BasicRectangle'' **η μεταβλητή r1 είναι και τύπου BasicRectangle**. Επομένως, θα μπορούσαμε να γράψουμε
  
 <code java> <code java>
-Bicycle myBicycle myBike+BasicRectangle r2 r1
-   //ή +   //ή ισοδύναμα 
-Βicycle yourBicycle = new MountainBike();+BasicRectangle r2 = new Rectangle(100,100,5,-5);
 </code> </code>
  
-Την παραπάνω ανάθεση την ονομάζουμε άρρητη μετατροπή (//implicit casting//) διότι αναθέτουμε μία μεταβλητή ενός τύπου δεδομένων (''myBike'') σε μία μεταβλητή γονικού τύπου δεδομένων (''myBicycle''), χωρίς να ορίζουμε μία μετατροπή τύπου (//type cast//).+Την παραπάνω ανάθεση την ονομάζουμε άρρητη μετατροπή (//implicit casting//) διότι αναθέτουμε ένα αντικείμενο του κληρονομούμενου τύπου δεδομένων (''r1'') σε μία μεταβλητή του γονικού τύπου (''r2''), χωρίς να ορίζουμε κάποια μετατροπή τύπου. 
 + 
 +Αν θέλουμε να ζωγραφίσουμε τον κώδικα του προηγούμενου παραδείγματος μπορούμε να το κάνουμε όπως στο παρακάτω σχήμα. Παρατηρήστε ότι η μεταβλητές **r1** και **r2** δείχνουν στο ίδιο αντικείμενο. Η διαφορά είναι ότι η **r2** αν και δείχνει σε ένα αντικείμενο τύπου **Rectangle**, έχει πρόσβαση μόνο στο τμήμα του αντικειμένου που είναι του τύπου **BasicRectangle**. Ο λόγος για αυτόν τον περιορισμό είναι ότι λόγω του τύπου της ο //compiler// υποθέτει ότι δείχνει σε ένα αντικείμενο τύπου **BasicRectangle** με αποτέλεσμα να μην επιτρέπει την πρόσβαση στα πεδία και τις μεθόδους που δεν ανήκουν στην κλάση **BasicRectangle**, αλλά στην υποκλάση. 
 + 
 +{{  :java:implicit-casting.png  |}} 
 + 
 +=== Ρητή μετατροπή ===
  
 Ας δοκιμάσουμε το ανάποδο παράδειγμα τώρα Ας δοκιμάσουμε το ανάποδο παράδειγμα τώρα
  
 <code java> <code java>
-Bycycle myBicycle = new Bicycle(); +BasicRectangle r3 = new Rectangle(100,200,5,-5); 
-MountainBike myBike myBicycle;+Rectangle r4 r3;
 </code> </code>
  
-Σε αυτή την περίπτωση ο compiler διαμαρτύρεται, διότι η μεταβλητή ''myBicycle'' είναι τύπου ''Bicycle'' και δεν είναι απαραίτητο ότι είναι και τύπου ''MountainBike''. Αν θέλουμε να ξεπεράσουμε το παραπάνω μήνυμα λάθους του compiler θα πρέπει να γράψουμε το εξής:+Σε αυτή την περίπτωση ο //compiler// διαμαρτύρεται, διότι η μεταβλητή ''r3'' είναι τύπου ''BasicRectangle'' και όχι τύπου ''Rectangle''. Αν θέλουμε να ξεπεράσουμε το παραπάνω μήνυμα λάθους του compiler θα πρέπει να γράψουμε το εξής:
  
 <code java> <code java>
-Bycycle myBicycle = new Bicycle(); +BasicRectangle r3 = new Rectangle(100,200,5,-5); 
-MountainBike myBike = (MountainBikemyBicycle;+Rectangle r4 = (Rectangle)r3;
 </code> </code>
  
-Εδώ ενημερώνουμε τον compiler ότι η μεταβλητή ''myBicycle'' είναι και τύπου ''MountainBike'', λαμβάνοντας ο προγραμματιστής την ευθύνη ότι αυτό ισχύει. Εάν δεν ισχύει, κατά την εκτέλεση του προγράμματος θα παραχθεί μία εξαίρεση (exception)*. Θα δούμε πιο κάτω τι είναι και πως διαχειριζόμαστε τις εξαιρέσεις.+Σε αυτή την περίπτωση ο προγραμματιστής βεβαιώνει τον //compiler// ότι η μεταβλητή ''r4'' είναι και τύπου ''Rectangle''. Την παραπάνω ανάθεση την ονομάζουμε ρητή μετατροπή (//explicit casting//). Επειδή δεν ισχύει η παραπάνω μετατροπή, κατά την εκτέλεση του προγράμματος θα παραχθεί μία εξαίρεση (//exception//). Θα δούμε πιο κάτω τι είναι οι εξαιρέσεις και πως τις διαχειριζόμαστε.
  
-Ένας πιο ασφαλής τρόπος για να επαναλάβουμε τον παραπάνω κώδικα, χωρίς να παραχθεί εξαίρεση είναι ο εξής:+Ένας πιο ασφαλής τρόπος για να επαναλάβουμε τον παραπάνω κώδικα, χωρίς να παραχθεί εξαίρεση είναι ο παρακάτω. Εδώ η μετατροπή γίνεται αφού πρώτα γίνει έλεγχος ότι το αντικείμενο για το οποίο θα γίνει μετατροπή τύπου είναι και του νέου τύπου. Η μετατροπή θα γίνει μόνο εφόσον ο έλεγχος επιτύχει.
  
 <code java> <code java>
-Bycycle myBicycle = new Bicycle(); +BasicRectangle r3 = new Rectangle(100,200,5,-5); 
-MountainBike myBike+Rectangle r4
-if (myBicycle instanceof MountainBike) { +if (r3 instanceof Rectangle) { 
-    myBike = (MountainBike)myBicycle;+    r4 = (Rectangle)r3;
 } }
 </code> </code>
  
-===== Κριτήρια χρήσης της κληρονομικότητας ως εργαλείο ανάπτυξης λογισμικού ===== +ροηγούμενο: [[ :java:inheritance | Κληρονομικότητα ]] [[:toc | Περιεχόμενα]] | Επόμενο: [[ :java:inheritance_subclassing_vs_encapsulating | Κριτήριχρήσης της κληρονομικότητας ]]|
- +
-Ας επανέλθουμε στο παράδειγμα του ορθογωνίου παραλληλογράμμου το οποίο έχουμε συναντήσει αρκετές φορές στο παρελθόν και ας προσπαθήσουμε να δημιουργήσουμε την κλάση ενός [[wp>Cuboid|κυβοειδούς]] με χρήση της υφιστάμενης κλάσης του [[java:class|ορθογωνίου παραλληλογράμμου]]. +
- +
-Πριν ξεκινήσουμε την υλοποίηση θα πρέπει να αποφασίσουμε εάν θέλουμε να δημιουργήσουμε το κυβοειδές χρησιμοποιώντας ως μεταβλητή της νέας κλάσης ένα αντικείμενο της κλάσης //Rectangle// ή επιθυμούμε να επεκτείνουμε την κλάση //Rectangle// μέσω της νέας κλάσης. Δείτε παρακάτω τις δύο παραλλαγές της κλάσης //Cuboid// με και χωρίς κληρονομικότητα. +
- +
-<code java Cuboid.java> +
-public class Cuboid { +
-  Rectangle rec; +
-  int length; +
-   +
-  public Cuboid(int l, int w, int h) { +
-    rec = new Rectangle(w,h); +
-    length = l; +
-  } +
-   +
-  public int getLength() { return length; } +
-  public void setLength(int l) { length = l; } +
-   +
-  public int volume() { return length * rec.area(); } +
-+
-</code> +
- +
-ή  +
- +
-<code java Cuboid.java> +
-public class Cuboid extends Rectangle { +
-  int length; +
-   +
-  public Cuboid(int l, int w, int h) { +
-    super(w,h); +
-    length = l; +
-  } +
-   +
-  public int getLength() { return length; } +
-  public void setLength(int l) { length = l; } +
-   +
-  public int volume() { return length * area(); } +
-+
-</code> +
- +
-Και οι δύο κλάσεις μεταγλωττίζονται και λειτουργικά παράγουν το ίδιο αποτέλεσμα. Το ερώτημα είναι ποια από τις δύο μεθόδους θα προτιμήσουμε. Η απάντηση είναι απλή και συνίσταται στο εξής: Εάν ο νέος τύπος δεδομένων που προκύπτει είναι της ίδιας κατηγορίας με τον τύπο δεδομένων της αρχικής κλάσης τότε μπορούμε να χρησιμοποιήσουμε κληρονομικότητα. Εάν όμως ο νέος τύπος δεδομένων δεν είναι της ίδιας κατηγορίας με τον προηγούμενο τότε η 1η επιλογή είναι η βελτιστη.  +
- +
-Για παράδειγμα, [[lib/exe/detail.php?id=java%3Ainheritance&media=java:super_sub_class.jpg|στο αρχικό παράδειγμα της κληρονομικότητας]], από τον +
java/type_casting.1455514710.txt.gz · Last modified: 2016/02/15 05:38 by gthanos