java:generic_interface_example

Differences

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

Link to this comparison view

java:generic_interface_example [2016/04/14 15:23]
gthanos [Εισάγοντας μία νέα κλάση που υλοποιεί το Interface]
java:generic_interface_example [2020/02/25 09:34]
Line 1: Line 1:
-====== Παράδειγμα δημιουργίας και χρήσης ενός interface ====== 
- 
-Ας επανέλθουμε στο παράδειγμα [[java:interfaces#Χρησιμοποιώντας ένα interface ως τύπο δεδομένων|χρήσης των interfaces ως τύπους δεδομένων]] και ας αλλάξουμε ελαφρά το interface MyComparable ώστε να περιέχει και την μέθοδο isEqual που ελέγχει την ισότητα. 
- 
-<code java MyComparable.java> 
-public interface MyComparable { 
-  public boolean isLarger(MyComparable other) throws InvalidComparableTypeException; 
-  public boolean isEqual(MyComparable other) throws InvalidComparableTypeException; 
-} 
-</code> 
- 
-Η κλάση **InvalidComparableTypeException** ορίζεται ως εξής: 
-<code java InvalidComparableTypeException.java> 
-class InvalidComparableTypeException extends Exception { 
-} 
-</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) throws InvalidComparableTypeException { 
-    if( other instanceof Rectangle ) { 
-      Rectangle otherRect = (Rectangle) other; 
-      return (this.getArea() > otherRect.getArea()); 
-    } 
-    throw new InvalidComparableTypeException(); 
-  } 
-   
-  @Override 
-  public boolean isEqual(MyComparable other) throws InvalidComparableTypeException { 
-    if( other instanceof Rectangle ) { 
-      Rectangle otherRect = (Rectangle) other; 
-      return (this.getArea() == otherRect.getArea()); 
-    } 
-    throw new InvalidComparableTypeException(); 
-  } 
-  
-  @Override 
-  public String toString() { 
-    return origin.toString() + ", " + width + " X " + height ; 
-  } 
-  
-  public double getArea() { 
-       return (double)width * height; 
-  } 
- 
-</code> 
- 
-Παρατηρήστε ότι υλοποιούμε το interface MyComparable συγκρίνοντας τα αντικείμενου τύπου Rectangle με βάση το εμβαδόν τους. Επιπλέον έχετε την κλάση MyComparableUtil που συγκρίνει αντικείμενα τύπου MyComparable ως εξής: 
- 
-<code java MyComparableUtil.java> 
-public class MyComparableUtil { 
-  /** 
-   * Returns the larger among the two objects. If objects are equal returns null. 
-   */ 
-  public static MyComparable findLarger(MyComparable object1, MyComparable object2) throws InvalidComparableTypeException { 
-    if(object1.isLarger(object2)) 
-      return object1; 
-    else if( object1.isEqual(object2) ) 
-      return null; 
-    return object2; 
-  } 
-   
-  /** 
-   * Returns the smaller among the two objects. If objects are equal returns null. 
-   */ 
-  public static MyComparable findSmaller(MyComparable object1, MyComparable object2) throws InvalidComparableTypeException { 
-    if(!object1.isLarger(object2)) 
-      return object1; 
-    else if( object1.isEqual(object2) ) 
-      return null; 
-    return object2; 
-  } 
-} 
-</code> 
- 
-<code java CompareObjects.java> 
-public class CompareObjects { 
-  public static void main (String []args) { 
-    try { 
-      Point p = new Point(1,1); 
-      Rectangle rec1 = new Rectangle(10, 20, p); 
-      Rectangle rec2 = new Rectangle(10, 22, p); 
-     
-      System.out.println("Larger objet is "+ MyComparableUtil.findLarger(rec1, rec2)); 
-    } catch(InvalidComparableTypeException ex) { 
-      System.err.println("Unable to compare objects!"); 
-    } 
-  } 
-} 
-</code> 
- 
- 
-Ας υποθέσουμε τώρα ότι θέλετε να φτιάξετε την κλάση Circle (άλλο διδιάστατο σχήμα) που υλοποιεί και αυτή το interface MyComparable. Δείτε την κλάση Circle παρακάτω. 
- 
-<code java Circle.java> 
-public class Circle implements MyComparable{ 
-  private Point origin; 
-  private int radius; 
- 
-  public Circle(Point origin, int radius) { 
-    this.origin = origin; 
-    this.radius = radius; 
-  } 
-   
-  public void setOrigin(Point newOrigin) { 
-    origin = newOrigin; 
-  } 
-   
-  public Point getOrigin() { return origin; } 
-   
-  public void setRadius(int newRadius ) { 
-    radius = newRadius; 
-  } 
-   
-  public int getRadius() { return radius; } 
-   
-  public double getArea() { 
-    return 3.14159 * radius * radius; 
-  } 
-   
-  @Override 
-  public boolean isLarger(MyComparable other) throws InvalidComparableTypeException { 
-    if( other instanceof Circle ) { 
-      Circle otherRect = (Circle) other; 
-      return (this.getArea() > otherRect.getArea()); 
-    } 
-    throw new InvalidComparableTypeException(); 
-  } 
-   
-  @Override 
-  public boolean isEqual(MyComparable other) throws InvalidComparableTypeException { 
-    if( other instanceof Circle ) { 
-      Circle otherRect = (Circle) other; 
-      return (this.getArea() == otherRect.getArea()); 
-    } 
-    throw new InvalidComparableTypeException(); 
-  } 
-   
-  public String toString() { 
-    return origin.toString()+" radius: "+radius; 
-  } 
-} 
-</code> 
- 
-Αν αναδιαμορφώσουμε την //CompareObjects// ως εξής: 
- 
-<code java CompareObjects.java> 
-public class CompareObjects { 
-  public static void main (String []args) { 
-    try { 
-      Point p = new Point(1,1); 
-      Rectangle rect = new Rectangle(10, 20, p); 
-      Circle circle = new Circle(p, 12); 
-     
-      System.out.println("Larger objet is "+ MyComparableUtil.findLarger(rect, circle)); 
-    } catch(InvalidComparableTypeException ex) { 
-      System.err.println("Unable to compare objects!"); 
-    } 
-  } 
-} 
-</code> 
- 
-παρατηρούμε ότι η παραπάνω κλάση μεταγλωττίζεται, αλλά όταν θα επιχειρήσετε να την τρέξετε θα παραχθεί το exception //InvalidComparableTypeException//. Παρατηρούμε δηλαδή ότι είναι αδύνατον να συγκρίνουμε διδιάστατα αντικείμενα που ανήκουν σε διαφορετικά σχήματα. Προκειμένου να αντιμετωπίσουμε το παραπάνω πρόβλημα η λύση είναι να φτιάξουμε μία ενδιάμεση κλάση η οποία να συγκρίνει τα διδιάστατα σχήματα με βάση το εμβαδό τους, δηλαδή με βάση την μέθοδο **getArea()**. Ας ονομάσουμε την κλάση αυτή **TwoDShape**: 
- 
-<code java TwoDShape.java> 
- 
-public abstract class TwoDShape implements MyComparable { 
- 
-  public final boolean isLarger(MyComparable other) throws InvalidComparableTypeException { 
-    if( other instanceof TwoDShape ) { 
-      TwoDShape obj = (TwoDShape)other; 
-      if( this.getArea() > obj.getArea() )  
-        return true; 
-      else  
-        return false; 
-     } 
-     throw new InvalidComparableTypeException(); 
-  } 
-   
-  public final boolean isEqual(MyComparable other) throws InvalidComparableTypeException { 
-    if( other instanceof TwoDShape ) { 
-      TwoDShape obj = (TwoDShape)other; 
-      if( this.getArea() == obj.getArea() )  
-        return true; 
-      else  
-        return false; 
-    } 
-    throw new InvalidComparableTypeException(); 
-  } 
-   
-  public abstract double getArea(); 
-} 
-</code> 
- 
-<WRAP important 80% center round> 
-Παρατηρήστε τα εξής: 
-  - Η μέθοδος isLarger για τα διδιάστατα σχήματα βασίζεται στη μέθοδο getArea(). Η μέθοδος getArea() ορίζεται στην κλάση TwoDShape, αλλά η υλοποίηση της εξαρτάται από το εκάστοτε διδιάστατο σχήμα. Κατά συνέπεια, η μέθοδος δηλώνεται ως abstract. Η μέθοδος getArea() θα οριστεί σε κάθε υποκλάση της TwoDShape. Η κλάση που περιέχει μία abstract μέθοδο είναι και αυτή abstract. 
-  - H μέθοδος isLarger συγκρίνει τα διδιάστατα σχήματα με βάση το εμβαδό τους. Προκειμένου κάποια υποκλάση να μην επαναορίσει την μέθοδο isLarger με τρόπου που δεν είναι επιθυμητός, ώστε να εξακολουθούμε να μπορούμε να συγκρίνουμε διδιάστατα σχήματα μεταξύ τους ορίζουμε την μέθοδο ως final. 
-</WRAP> 
- 
-Με βάση τα παραπάνω οι κλάσεις Rectangle και Circle γίνονται ως εξής: 
- 
-<code java Rectangle.java> 
-public class Rectangle extends TwoDShape { 
-     
-  // 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 String toString() { 
-    return origin.toString() + ", " + width + " X " + height ; 
-  } 
-  
-  public double getArea() { 
-       return width * height; 
-  } 
- 
-</code> 
- 
-<code java Circle.java> 
- 
-public class Circle extends TwoDShape { 
-  private Point origin; 
-  private int radius; 
- 
-  public Circle(Point origin, int radius) { 
-    this.origin = origin; 
-    this.radius = radius; 
-  } 
-   
-  public void setOrigin(Point newOrigin) { 
-    origin = newOrigin; 
-  } 
-   
-  public Point getOrigin() { return origin; } 
-   
-  public void setRadius(int newRadius ) { 
-    radius = newRadius; 
-  } 
-   
-  public int getRadius() { return radius; } 
-   
-  public double getArea() { 
-    return 3.14159 * radius * radius; 
-  } 
-   
-  public String toString() { 
-    return origin.toString()+" radius: "+radius; 
-  } 
-} 
-</code> 
- 
-Επιχειρώντας τώρα να τρέξετε τη κλάση CompareObjects παρατηρήστε ότι τρέχει χωρίς πρόβλημα. 
- 
-===== Εισάγοντας μία νέα κλάση που υλοποιεί το Interface ===== 
- 
-Σε αναλογία με τα παραπάνω ας υποθέσουμε ότι φτιάχνουμε την κλάση ThreeDShape που υλοποιεί και αυτή το interface  MyComparable. Η κλάση ThreeDShape έχει και αυτή την δική της υποκλάση Cuboid.  
- 
-<code java ThreeDShape.java> 
- 
-public abstract class ThreeDShape implements MyComparable { 
- 
-  public final boolean isLarger(MyComparable other) throws InvalidComparableTypeException { 
-    if( other instanceof ThreeDShape ) { 
-      ThreeDShape obj = (ThreeDShape)other; 
-      if( this.getArea() > obj.getArea() )  
-        return true; 
-      else  
-        return false; 
-     } 
-     throw new InvalidComparableTypeException(); 
-  } 
-   
-  public final boolean isEqual(MyComparable other) throws InvalidComparableTypeException { 
-    if( other instanceof ThreeDShape ) { 
-      ThreeDShape obj = (ThreeDShape)other; 
-      if( this.getArea() == obj.getArea() )  
-        return true; 
-      else  
-        return false; 
-    } 
-    throw new InvalidComparableTypeException(); 
-  } 
-   
-  public abstract double getVolume(); 
-   
-  public abstract double getArea(); 
-} 
-</code> 
- 
-<code java Cuboid.java> 
-public class Cuboid extends ThreeDShape { 
-  Rectangle rec; 
-  int depth; 
-   
-  public Cuboid( Rectangle rec, int depth) { 
-    this.rec = rec; 
-    this.depth = depth; 
-  } 
-   
-  public double getVolume() { 
-    return rec.getArea() * depth; 
-  } 
-   
-  public double getArea() { 
-    return 2 * ( depth * rec.getWidth() + depth * rec.getHeight() + rec.getArea() );  
-  } 
-   
-  public String toString() { 
-    return rec.toString() + " ,depth: "+depth; 
-  } 
-} 
-</code> 
- 
-Ας υποθέσουμε τώρα ότι επιχειρούμε να μεταγλωττίσουμε και να τρέξουμε την παρακάτω έκδοση της κλάσης CompareObjects 
- 
-<code java CompareObjects.java> 
-public class CompareObjects { 
-  public static void main (String []args) { 
-    try { 
-      Point p = new Point(1,1); 
-      Rectangle rect = new Rectangle(10, 20, p); 
-      Cuboid cuboid = new Cuboid(rect, 15); 
-     
-      System.out.println("Larger objet is "+ MyComparableUtil.findLarger(rect, cuboid)); 
-    } catch(InvalidComparableTypeException ex) { 
-      System.err.println("Unable to compare objects!"); 
-    } 
-  } 
-} 
-</code> 
- 
-< 
-Ο παρακάτω κώδικας ΔΕΝ θα έπρεπε να δουλεύει καθώς επιχειρεί να συγκρίνει ένα διδιάστατο με ένα τρισδιάστατο σχήμα που είναι μη συγκρίσιμα. Πράγματι δεν δουλεύει καθώς παράγει ένα exception InvalidComparableTypeException. __Ιδανικά θα θέλαμε ένα σφάλμα αυτού του τύπου να το αντιληφθούμε κατά την μεταγλώττιση του προγράμματος και όχι κατά την εκτέλεση του__.  
- 
-Η λύση στο πρόβλημα είναι η χρήση παραμετρικών τύπων δεδομένων (generics). __Οι παραμετρικοί τύποι δεδομένων έχουν την δυνατότητα να αντιλαμβάνονται ασυμβατότητες τύπων δεδομένων κατά την εκτέλεση και όχι κατά την μεταγλώττιση.__ Δείτε πως διαμορφώνονται όλες οι παραπάνω κλάσεις με χρήση generics. 
- 
-<code java MyComparable.java> 
-  
-public interface MyComparable<T> { 
-  public boolean isLarger(T other); 
-} 
-</code> 
- 
-<code java TwoDShape.java> 
-public abstract class TwoDShape implements MyComparable<TwoDShape> { 
- 
-  public final boolean isLarger(TwoDShape other) { 
-      if( this.getArea() > other.getArea() )  
-        return true; 
-      else  
-        return false; 
-  } 
-   
-  public final boolean isEqual(TwoDShape other) { 
-      if( this.getArea() > other.getArea() )  
-        return true; 
-      else  
-        return false; 
-  } 
-   
-  public abstract double getArea(); 
-} 
-</code> 
- 
-<code java ThreeDShape.java> 
-public abstract class ThreeDShape implements MyComparable<ThreeDShape> { 
- 
-  public final boolean isLarger(ThreeDShape other) { 
-      if( this.getArea() > other.getArea() )  
-        return true; 
-      else  
-        return false; 
-  } 
-   
-  public final boolean isEqual(ThreeDShape other) { 
-      if( this.getArea() > other.getArea() )  
-        return true; 
-      else  
-        return false; 
-  } 
-   
-  public abstract double getArea(); 
-  public abstract double getVolume();  
-} 
-</code> 
- 
-<code java MyComparableUtil.java> 
-public class MyComparableUtil <T extends MyComparable<T>> { 
-   
-  public T findLarger(T object1, T object2) { 
-    if (object1.isLarger(object2)) 
-      return object1; 
-    else  
-      return object2; 
-  } 
-   
-  public T findSmaller(T object1, T object2) { 
-    if (!(object1.isLarger(object2))) 
-      return object1; 
-    else  
-      return object2; 
-  } 
-} 
-</code> 
- 
-<WRAP important 80% center round> 
-Παρατηρήστε ότι δεν έχει νόημα η παραγωγή του InvalidComparableTypeException, καθώς η ασυμβατότητα των τύπων εντοπίζεται κατά την διάρκεια της μεταγλώττισης και όχι της εκτέλεσης του κώδικα. 
-</WRAP> 
- 
-Αν προσπαθήσετε να μεταγλωττίσετε την CompareObjects θα δείτε ότι είναι αδύνατον να το κάνετε. 
- 
-<code java CompareObjects.java> 
-public class CompareObjects { 
-  public static void main (String []args) { 
-    Point p = new Point(1,1); 
-    Rectangle rect = new Rectangle(10, 20, p); 
-    Cuboid cuboid = new Cuboid(rect, 15); 
-     
-    MyComparableUtil util = new MyComparableUtil(); 
-   
-    System.out.println("Larger objet is "+ util.findLarger(rect, cuboid)); 
-  } 
-} 
-</code> 
- 
- 
- 
- 
- 
  
java/generic_interface_example.txt · Last modified: 2020/02/25 09:34 (external edit)