User Tools

Site Tools


java:generic_interface_example

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:generic_interface_example [2016/04/14 15:17] – [Εισάγοντας μία νέα κλάση που υλοποιεί το Interface] gthanosjava:generic_interface_example [2020/02/25 09:34] (current) – external edit 127.0.0.1
Line 1: Line 1:
-====== Παράδειγμα δημιουργίας και χρήσης ενός interface ======+====== Παράδειγμα χρήσης διεπαφής σε συνδυασμό με Abstract κλάση (περιέχει και generics στο τελευταίο μέρος της λύσης======
  
-Ας επανέλθουμε στο παράδειγμα [[java:interfaces#Χρησιμοποιώντας ένα interface ως τύπο δεδομένων|χρήσης των interfaces ως τύπους δεδομένων]] και ας αλλάξουμε ελαφρά το interface MyComparable ώστε να περιέχει και την μέθοδο isEqual που ελέγχει την ισότητα.+Ας επανέλθουμε στο παράδειγμα [[java:interface_as_data_type|χρήσης των interfaces ως τύπους δεδομένων]] και ας αλλάξουμε ελαφρά το interface MyComparable ώστε να περιέχει και την μέθοδο isEqual που ελέγχει την ισότητα.
  
 <code java MyComparable.java> <code java MyComparable.java>
Line 18: Line 18:
 και είναι απαραίτητη ώστε να σηματοδοτήσουμε την πιθανή σύγκριση ασύμβατων μεταξύ τους τύπων δεδομένων. και είναι απαραίτητη ώστε να σηματοδοτήσουμε την πιθανή σύγκριση ασύμβατων μεταξύ τους τύπων δεδομένων.
  
-Στη συνέχεια κατασκευάζουμε την κλάση Rectangle που υλοποιεί το συγκεκριμένο interface ως εξής:+Στη συνέχεια κατασκευάζουμε την κλάση Rectangle που υλοποιεί το συγκεκριμένο interface:
  
 <code java Rectangle.java> <code java Rectangle.java>
Line 90: Line 90:
 </code> </code>
  
-Παρατηρήστε ότι υλοποιούμε το interface MyComparable συγκρίνοντας τα αντικείμενου τύπου Rectangle με βάση το εμβαδόν τους. Επιπλέον έχετε την κλάση MyComparableUtil που συγκρίνει αντικείμενα τύπου MyComparable ως εξής:+Παρατηρήστε ότι υλοποιούμε το //interface MyComparable// συγκρίνοντας τα αντικείμενου τύπου Rectangle __με βάση το εμβαδόν τους__. Επιπλέον ορίζουμε την κλάση //MyComparableUtil// που δίνει δύο μεθόδους σύγκρισης αντικείμενων τύπου MyComparable:
  
 <code java MyComparableUtil.java> <code java MyComparableUtil.java>
Line 117: Line 117:
 } }
 </code> </code>
 +
 +Τέλος η κλάση //CompareObjects// παρέχει τη //main// μέθοδο που θα χρειαστούμε για να εκτελέσουμε το πρόγραμμα.
  
 <code java CompareObjects.java> <code java CompareObjects.java>
Line 135: Line 137:
  
  
-Ας υποθέσουμε τώρα ότι θέλετε να φτιάξετε την κλάση Circle (άλλο διδιάστατο σχήμα) που υλοποιεί και αυτή το interface MyComparable. Δείτε την κλάση Circle παρακάτω.+Ας υποθέσουμε τώρα ότι θέλετε να φτιάξετε την κλάση //Circle// που απεικονίζει τον κύκλο και υλοποιεί και αυτή το //interface MyComparable//
  
 <code java Circle.java> <code java Circle.java>
Line 187: Line 189:
 </code> </code>
  
-Αν αναδιαμορφώσουμε την //CompareObjects// ως εξής:+Ας προσπαθήσουμε τώρα στην //CompareObjects// να συγκρίνουμε ένα ορθογώνιο παραλληλόγραμμο με ένα κύκλο.
  
 <code java CompareObjects.java> <code java CompareObjects.java>
Line 205: Line 207:
 </code> </code>
  
-παρατηρούμε ότι η παραπάνω κλάση μεταγλωττίζεται, αλλά όταν θα επιχειρήσετε να την τρέξετε θα παραχθεί το exception //InvalidComparableTypeException//. Παρατηρούμε δηλαδή ότι είναι αδύνατον να συγκρίνουμε διδιάστατα αντικείμενα που ανήκουν σε διαφορετικά σχήματα. Προκειμένου να αντιμετωπίσουμε το παραπάνω πρόβλημα η λύση είναι να φτιάξουμε μία ενδιάμεση κλάση η οποία να συγκρίνει τα διδιάστατα σχήματα με βάση το εμβαδό τους, δηλαδή με βάση την μέθοδο **getArea()**. Ας ονομάσουμε την κλάση αυτή **TwoDShape**:+Παρατηρούμε ότι η παραπάνω κλάση μεταγλωττίζεται, αλλά όταν θα επιχειρήσετε να την τρέξετε θα παραχθεί το exception //InvalidComparableTypeException// και θα τυπωθεί το μήνυμα μέσα στο //catch block//. Eίναι αδύνατον να συγκρίνουμε διδιάστατα αντικείμενα που ανήκουν σε διαφορετικά σχήματα, αν και το μέτρο σύγκρισης του εμβαδού που υιοθετούμε είναι κοινό και στις δύο κλάσεις  
 + 
 +Προκειμένου να μπορούμε να συγκρίνουμε διαφορετικά διδιάστατα σχήματα μεταξύ τους η λύση είναι να φτιάξουμε μία ενδιάμεση κλάση η οποία να συγκρίνει τα διδιάστατα σχήματα με βάση το εμβαδό τους, δηλαδή με βάση την μέθοδο **getArea()**. Ας ονομάσουμε την κλάση αυτή **TwoDShape**:
  
 <code java TwoDShape.java> <code java TwoDShape.java>
Line 237: Line 241:
 </code> </code>
  
-<WRAP important 80% center round>+<WRAP important 90% center round>
 Παρατηρήστε τα εξής: Παρατηρήστε τα εξής:
   - Η μέθοδος isLarger για τα διδιάστατα σχήματα βασίζεται στη μέθοδο getArea(). Η μέθοδος getArea() ορίζεται στην κλάση TwoDShape, αλλά η υλοποίηση της εξαρτάται από το εκάστοτε διδιάστατο σχήμα. Κατά συνέπεια, η μέθοδος δηλώνεται ως abstract. Η μέθοδος getArea() θα οριστεί σε κάθε υποκλάση της TwoDShape. Η κλάση που περιέχει μία abstract μέθοδο είναι και αυτή abstract.   - Η μέθοδος isLarger για τα διδιάστατα σχήματα βασίζεται στη μέθοδο getArea(). Η μέθοδος getArea() ορίζεται στην κλάση TwoDShape, αλλά η υλοποίηση της εξαρτάται από το εκάστοτε διδιάστατο σχήμα. Κατά συνέπεια, η μέθοδος δηλώνεται ως abstract. Η μέθοδος getArea() θα οριστεί σε κάθε υποκλάση της TwoDShape. Η κλάση που περιέχει μία abstract μέθοδο είναι και αυτή abstract.
-  - H μέθοδος isLarger συγκρίνει τα διδιάστατα σχήματα με βάση το εμβαδό τους. Προκειμένου κάποια υποκλάση να μην επαναορίσει την μέθοδο isLarger με τρόπου που δεν είναι επιθυμητός, ώστε να εξακολουθούμε να μπορούμε να συγκρίνουμε διδιάστατα σχήματα μεταξύ τους ορίζουμε την μέθοδο ως final.+  - H μέθοδος isLarger συγκρίνει τα διδιάστατα σχήματα με βάση το εμβαδό τους. Προκειμένου κάποια υποκλάση να μην επαναορίσει την μέθοδο isLarger με τρόπο που δεν είναι επιθυμητός, ώστε να εξακολουθούμε να μπορούμε να συγκρίνουμε διδιάστατα σχήματα μεταξύ τουςορίζουμε την μέθοδο ως final.
 </WRAP> </WRAP>
  
Line 392: Line 396:
 </code> </code>
  
-Ας υποθέσουμε τώρα ότι επιχειρούμε να μεταγλωττίσουμε και να τρέξουμε την παρακάτω έκδοση της κλάσης CompareObjects+Ας υποθέσουμε τώρα ότι επιχειρούμε συγκρίνουμε ένα διδιάστατο με ένα τρισδιάστατο σχήμα. Μεταβάλλουμε κατάληλλα την κλάση //CompareObjects// και επιχειρούμε να μεταγλωττίσουμε και να τρέξουμε.
  
 <code java CompareObjects.java> <code java CompareObjects.java>
Line 402: Line 406:
       Cuboid cuboid = new Cuboid(rect, 15);       Cuboid cuboid = new Cuboid(rect, 15);
          
-      System.out.println("Larger objet is "+ MyComparableUtil.findLarger(rec, cuboid));+      System.out.println("Larger objet is "+ MyComparableUtil.findLarger(rect, cuboid));
     } catch(InvalidComparableTypeException ex) {     } catch(InvalidComparableTypeException ex) {
       System.err.println("Unable to compare objects!");       System.err.println("Unable to compare objects!");
Line 410: Line 414:
 </code> </code>
  
-+Ο παρακάτω κώδικας δεν θα έπρεπε να δουλεύει καθώς επιχειρεί να συγκρίνει ένα διδιάστατο με ένα τρισδιάστατο σχήμα που είναι μη συγκρίσιμα. Πράγματι δεν δουλεύει καθώς παράγει ένα exception InvalidComparableTypeException. __Ιδανικά όμως θα θέλαμε ένα σφάλμα αυτού του τύπου να το αντιληφθούμε κατά την μεταγλώττιση του προγράμματος και όχι κατά την εκτέλεση του__. 
-Ο παρακάτω κώδικας ΔΕΝ θα έπρεπε να δουλεύει καθώς επιχειρεί να συγκρίνει ένα διδιάστατο με ένα τρισδιάστατο σχήμα που είναι μη συγκρίσιμα. Πράγματι δεν δουλεύει καθώς παράγει ένα exception InvalidComparableTypeException. __Ιδανικά θα θέλαμε ένα σφάλμα αυτού του τύπου να το αντιληφθούμε κατά την μεταγλώττιση του προγράμματος και όχι κατά την εκτέλεση του__. +
  
-Η λύση στο πρόβλημα είναι η χρήση παραμετρικών τύπων δεδομένων (generics). __Οι παραμετρικοί τύποι δεδομένων έχουν την δυνατότητα να αντιλαμβάνονται ασυμβατότητες τύπων δεδομένων κατά την εκτέλεση και όχι κατά την μεταγλώττιση.__ Δείτε πως διαμορφώνονται όλες οι παραπάνω κλάσεις με χρήση generics.+Η λύση στο πρόβλημα είναι η χρήση παραμετρικών τύπων δεδομένων (generics). __Οι παραμετρικοί τύποι δεδομένων έχουν την δυνατότητα να αντιλαμβάνονται ασυμβατότητες τύπων δεδομένων κατά την μεταγλώττιση και όχι κατά την εκτέλεση__Δείτε πως διαμορφώνονται όλες οι παραπάνω κλάσεις με χρήση generics. 
 + 
 +===== Χρήση Generics για το προηγούμενο παράδειγμα =====
  
 <code java MyComparable.java> <code java MyComparable.java>
Line 419: Line 424:
 public interface MyComparable<T> { public interface MyComparable<T> {
   public boolean isLarger(T other);   public boolean isLarger(T other);
 +  public boolean isEqual(T other);
 } }
 </code> </code>
Line 433: Line 439:
      
   public final boolean isEqual(TwoDShape other) {   public final boolean isEqual(TwoDShape other) {
-      if( this.getArea() other.getArea() ) +      if( this.getArea() == other.getArea() ) 
         return true;         return true;
       else        else 
Line 454: Line 460:
      
   public final boolean isEqual(ThreeDShape other) {   public final boolean isEqual(ThreeDShape other) {
-      if( this.getArea() other.getArea() ) +      if( this.getArea() == other.getArea() ) 
         return true;         return true;
       else        else 
Line 466: Line 472:
  
 <code java MyComparableUtil.java> <code java MyComparableUtil.java>
-public class TwosComparator <T extends MyComparable<T>> {+public class MyComparableUtil <T extends MyComparable<T>> {
      
   public T findLarger(T object1, T object2) {   public T findLarger(T object1, T object2) {
     if (object1.isLarger(object2))     if (object1.isLarger(object2))
       return object1;       return object1;
 +    else if (object1.isEqual(object2))
 +      return null;
     else      else 
       return object2;       return object2;
Line 478: Line 486:
     if (!(object1.isLarger(object2)))     if (!(object1.isLarger(object2)))
       return object1;       return object1;
 +    else if (object1.isEqual(object2))
 +      return null;
     else      else 
       return object2;       return object2;
Line 485: Line 495:
  
 <WRAP important 80% center round> <WRAP important 80% center round>
-Παρατηρήστε ότι δεν έχει νόημα η παραγωγή του InvalidComparableTypeException, καθώς η ασυμβατότητα των τύπων εντοπίζεται κατά την διάρκεια της μεταγλώττισης και όχι της εκτέλεσης του κώδικα.+Παρατηρήστε τα εξής: 
 +  - Δεν έχει νόημα η παραγωγή του InvalidComparableTypeException, καθώς η ασυμβατότητα των τύπων εντοπίζεται κατά την διάρκεια της μεταγλώττισης και όχι της εκτέλεσης του κώδικα
 +  - Δεν είναι δυνατόν να ορίσετε την κλάση //MyComparableUtil// ως στατική κλάση, καθώς  περιέχει παραμετρικούς τύπους και ο compiler δεν το επιτρέπει.
 </WRAP> </WRAP>
  
-Αν προσπαθήσετε να μεταγλωττίσετε την CompareObjects θα δείτε ότι είναι αδύνατον να το κάνετε.+Προσαρμόζουμε κατάλληλα την κλάση //CompareObjects//, ώστε να ανταποκρίνεται στις παραπάνω αλλαγές. Αν προσπαθήσετε να μεταγλωττίσετε την CompareObjects θα δείτε ότι είναι αδύνατον να το κάνετε.
  
 <code java CompareObjects.java> <code java CompareObjects.java>
 public class CompareObjects { public class CompareObjects {
   public static void main (String []args) {   public static void main (String []args) {
-    try { +    Point p = new Point(1,1); 
-      Point p = new Point(1,1); +    Rectangle rect = new Rectangle(10, 20, p); 
-      Rectangle rect = new Rectangle(10, 20, p); +    Cuboid cuboid = new Cuboid(rect, 15);
-      Cuboid cuboid = new Cuboid(rect, 15);+
          
-      System.out.println("Larger objet is "MyComparableUtil.findLarger(rec, cuboid)); +    MyComparableUtil<TwoDShape> util = new MyComparableUtil<>(); 
-    } catch(InvalidComparableTypeException ex) { +   
-      System.err.println("Unable to compare objects!"); +    System.out.println("Larger objet is "util.findLarger(rect, cuboid));
-    }+
   }   }
 } }
 </code> </code>
  
 +Το μήνυμα που εμφανίζει ο compiler είναι το παρακάτω
 +<code txt compiler-error.txt>
 +CompareObjects.java:9: error: method findLarger in class MyComparableUtil<T> cannot be applied to given types;
 +    System.out.println("Larger objet is "+ util.findLarger(rect, cuboid));
 +                                               ^
 +  required: TwoDShape,TwoDShape
 +  found: Rectangle,Cuboid
 +  reason: actual argument Cuboid cannot be converted to TwoDShape by method invocation conversion
 +  where T is a type-variable:
 +    T extends MyComparable<T> declared in class MyComparableUtil
 +</code>
  
- +| Προηγούμενο : [[ :java:abstract_classes_vs_interfaces | Συγκρίνοντας Abstract Κλάσεις και Interfaces ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο: [[ :java:comparable | Συγκρίνοντας αντικείμενα μεταξύ τους ]]  |
- +
- +
java/generic_interface_example.1460647026.txt.gz · Last modified: 2016/04/14 14:17 (external edit)