User Tools

Site Tools


java:anon_inner_classes

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
java:anon_inner_classes [2018/03/21 09:32]
gthanos [Παράδειγμα - Ανώνυμη εμφωλευμένη κλάση ως υλοποίηση ενός interface]
java:anon_inner_classes [2021/04/12 06:21]
gthanos
Line 4: Line 4:
  
 Ανώνυμες εμφωλευμένες κλάσεις μπορούμε να υλοποιήσουμε όταν συντρέχουν ταυτόχρονα οι παρακάτω λόγοι:  Ανώνυμες εμφωλευμένες κλάσεις μπορούμε να υλοποιήσουμε όταν συντρέχουν ταυτόχρονα οι παρακάτω λόγοι: 
-  - επιθυμούμε την υλοποίηση εσωτερικής κλάσης+  - θέλουμε να υλοποιήσουμε μία εσωτερική κλάση. 
-  - η κλάση αυτή υλοποιεί ένα interface ή επεκτείνει μία άλλη κλάση (η κλάση που επεκτείνεται μπορεί να είναι abstract ή όχι) και  +  - η κλάση αυτή υλοποιεί ένα //interface// ή επεκτείνει μία υφιστάμενη κλάση (η κλάση που επεκτείνεται μπορεί να είναι //abstract// ή όχι) και  
-  - από την κλάση αυτή πρόκειται να δημιουργηθεί μόνο ένα αντικείμενο. +  - από την κλάση αυτή επιθυμούμε να δημιουργηθεί μόνο ένα αντικείμενο. 
    
-Σε αυτές τις περιπτώσεις η χρήση ανώνυμων κλάσεων μπορεί να είναι βολική, καθώς συμπιέζει τον όγκο του κώδικα. Από την άλλη πλευρά η εκτεταμένη χρήση ανώνυμων κλάσεων μπορεί να δημιουργήσει κώδικα που είναι δυσανάγνωστος.+Σε αυτές τις περιπτώσεις η χρήση ανώνυμων κλάσεων μπορεί να είναι βολική, καθώς συμπιέζει το μέγεθος του κώδικα. Από την άλλη πλευρά η εκτεταμένη χρήση ανώνυμων κλάσεων μπορεί να δημιουργήσει κώδικα που είναι δυσανάγνωστος.
  
 ===== Παράδειγμα - Ανώνυμη εμφωλευμένη κλάση ως υλοποίηση ενός interface ===== ===== Παράδειγμα - Ανώνυμη εμφωλευμένη κλάση ως υλοποίηση ενός interface =====
  
-Στο παρακάτω παράδειγμα ορίζουμε την κλάση **Student** η οποία έχει τα τρία (3) πεδία **firstName**, **lastName**, **AEM**. Στη μέθοδο **//main//** ορίζουμε μία λίστα (ArrayList) από δεδομένα τύπου **Student** τα οποία διαβάζουμε από το αρχείο students.txt. Θέλουμε να ταξινομήσουμε τα δεδομένα της λίστας κατά αύξουσα σειρά με δύο διαφορετικούς τρόπους α)με βάση τη σειρά επώνυμο/όνομα/ΑΕΜ και β) με βάση τη σειρά ΑΕΜ/επώνυμο/όνομα. Η ταξινόμηση των στοιχείων μίας λίστας μπορεί να γίνει με τη βοήθεια της στατικής μεθόδου [[https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#sort(java.util.List,%20java.util.Comparator)|Collections.sort(java.util.List, java.util.Comparator)]], όπου παρέχεται ένα **συγκριτής** (//comparator//) για την σύγκριση των στοιχείων της λίστας. Η σύγκριση έχει υλοποιηθεί με δύο ανώνυμες κλάσεις που υλοποιούν και οι δύο το //interface// [[https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html|java.util.Comparator]].+Στο παρακάτω παράδειγμα ορίζουμε την κλάση **Student** η οποία έχει τα τρία (3) πεδία **firstName**, **lastName**, **AEM**. Θέλουμε να ταξινομήσουμε τα δεδομένα της λίστας κατά αύξουσα σειρά με δύο διαφορετικούς τρόπους α) με βάση τη σειρά επώνυμο/όνομα/ΑΕΜ και β) με βάση τη σειρά ΑΕΜ/επώνυμο/όνομα. Η ταξινόμηση των στοιχείων μίας λίστας μπορεί να γίνει με τη βοήθεια της στατικής μεθόδου [[https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#sort(java.util.List,%20java.util.Comparator)|Collections.sort(java.util.List, java.util.Comparator)]], όπου παρέχεται ένας **συγκριτής** (//comparator//) για την σύγκριση των στοιχείων της λίστας. Η σύγκριση έχει υλοποιηθεί με δύο ανώνυμες κλάσεις που υλοποιούν και οι δύο το //interface// [[https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html|java.util.Comparator]].
  
-<code students.txt>+<code java Student.java> 
 +import java.util.Comparator; 
 +import java.util.*; 
 +import java.io.*; 
 + 
 +class Student { 
 +  String firstName; 
 +  String lastName; 
 +  int AEM; 
 + 
 +  public Student(int AEM, String firstName, String lastName) { 
 +    this.firstName = firstName; 
 +    this.lastName = lastName; 
 +    this.AEM = AEM; 
 +  } 
 +     
 +  public String toString() { 
 +    return String.format("%5d. %s, %s", AEM, lastName, firstName); 
 +  } 
 +   
 +  // First anonymous comparator class 
 +  static Comparator<Student> lexicographicCmp = new Comparator<Student>() { 
 +    public int compare(Student st1, Student st2) { 
 +      int cmp = st1.lastName.compareTo(st2.lastName); 
 +      if(cmp==0) 
 +        cmp = st1.firstName.compareTo(st2.firstName); 
 +      if(cmp==0) 
 +        cmp = st1.AEM - st2.AEM; 
 +      return cmp; 
 +    } 
 +  }; 
 + 
 +  public static void sortLexicographically(List<Student> students) {     
 +    Collections.sort(students, Student.lexicographicCmp); 
 +  } 
 +   
 +  public static void sortByAEM(List<Student> students) { 
 +    // Second anonymous comparator class 
 +    Collections.sort(students, new Comparator<Student>() { 
 +        public int compare(Student st1, Student st2) { 
 +          int cmp = cmp = st1.AEM - st2.AEM; 
 +          if(cmp==0) 
 +            cmp = st1.lastName.compareTo(st2.lastName);             
 +          if(cmp==0) 
 +            cmp = st1.firstName.compareTo(st2.firstName); 
 +          return cmp; 
 +        } 
 +      } 
 +    ); 
 +  } 
 +
 +</code> 
 + 
 +Στη μέθοδο **//main//** διαβάζουμε από το αρχείο students.txt και καταχωρούμε το περιεχόμενο του σε μία λίστα (ArrayList<Student>). Στη συνέχεια εκτυπώνουμε τα στοιχεία της λίστας 
 +  * με τη σειρά που τα διαβάσαμε 
 +  * με λεξικογραφική σειρά. 
 +  * με βάση το ΑΕΜ 
 + 
 +<code txt students.txt>
 4596 Super Man 4596 Super Man
 5819 Peter Pan 5819 Peter Pan
Line 26: Line 84:
 8744 Amelia Dray 8744 Amelia Dray
 </code> </code>
 +
 +<code java>
 +import java.io.*;
 +import java.util.*;
 +
 +public class SortListOfStudents {
 +  
 +  public static void readFromFile(List<Student> students, File f) {    
 +    try(Scanner sc = new Scanner(f)) {
 +      while(sc.hasNextLine()) {        
 +        students.add( new Student(sc.nextInt(), sc.next(), sc.next()) );
 +      }
 +    }
 +    catch(FileNotFoundException ex) {
 +      System.out.println("File \""+f.getName()+"\" was not found!");
 +    }
 +    catch(InputMismatchException ex) {
 +      System.out.println("Input mismatch while reading with scanner!!!");
 +      ex.printStackTrace();
 +      System.exit(-1);
 +    }
 +  }
 +  
 +  public static String toString(List<Student> students) {
 +    StringBuilder str = new StringBuilder();
 +    for(Student st : students) 
 +      str.append(st+"\n");
 +    str.append("---------------------------------\n");
 +    return str.toString();
 +  }
 +  
 +  public static void main(String []args) {
 +    if(args.length == 0) {
 +      System.out.println("Insufficient number of arguments!\n");
 +      return;
 +    }
 +    List<Student> students = new ArrayList<Student>();
 +    readFromFile(students, new File(args[0]));
 +    System.out.println(" --- Init Ordering ---\n");
 +    System.out.println(toString(students));
 +    Student.sortLexicographically(students);
 +    System.out.println(" --- Lexicographic Ordering ---\n");
 +    System.out.println(toString(students));
 +    Student.sortByAEM(students);
 +    System.out.println(" --- AEM Ordering ---\n");
 +    System.out.println(toString(students));
 +  }
 +}
 +</code>
 +
 +
 +===== Παράδειγμα - Ανώνυμη εμφωλευμένη κλάση ως επέκταση υφιστάμενης κλάσης =====
 +
 +Δείτε το προηγούμενο παράδειγμα παραλλαγμένο ως εξής. Αρχικά φτιάχνουμε την εσωτερική //abstract// κλάση **BasicComparator** που περιέχει μόνο την μέθοδο //equals// του //interface// [[https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html|java.util.Comparator]]. Στη συνέχεια ορίζουμε δύο ανώνυμες εμφωλευμένες κλάσεις (όπως στο προηγούμενο παράδειγμα), οι οποίες δεν υλοποιούν το //interface// java.util.Comparator, αλλά την εσωτερική //abstract// κλάση **BasicComparator**.
  
 <code java Student.java> <code java Student.java>
Line 45: Line 157:
   public String toString() {   public String toString() {
     return String.format("%5d. %s, %s", AEM, lastName, firstName);     return String.format("%5d. %s, %s", AEM, lastName, firstName);
 +  }
 +  
 +  abstract class BasicComparator implements Comparator<Student> {
 +   
   }   }
          
-  Comparator<Student> lexicographicCmp = new Comparator<Student>() {+  Comparator<Student> lexicographicCmp = new BasicComparator() {
     public int compare(Student st1, Student st2) {     public int compare(Student st1, Student st2) {
       int cmp = st1.lastName.compareTo(st2.lastName);       int cmp = st1.lastName.compareTo(st2.lastName);
Line 55: Line 171:
         cmp = st1.AEM - st2.AEM;         cmp = st1.AEM - st2.AEM;
       return cmp;       return cmp;
-    } +    }    
-    public boolean equals(Object o) { +
-      if(o instanceof Student) { +
-        Student st = (Student) o; +
-        if(firstName.equals(st.firstName) && lastName.equals(st.lastName) && AEM == st.AEM) +
-          return true; +
-      } +
-      return false; +
-    }+
   };   };
  
Line 87: Line 195:
          
   public void sortByAEM(List<Student> students) {   public void sortByAEM(List<Student> students) {
-    Collections.sort(students, new Comparator<Student>() {+    Collections.sort(students, new BasicComparator() {
         public int compare(Student st1, Student st2) {         public int compare(Student st1, Student st2) {
           int cmp = cmp = st1.AEM - st2.AEM;           int cmp = cmp = st1.AEM - st2.AEM;
Line 95: Line 203:
             cmp = st1.firstName.compareTo(st2.firstName);             cmp = st1.firstName.compareTo(st2.firstName);
           return cmp;           return cmp;
-        } +        }        
-        public boolean equals(Object o) { +
-          if(o instanceof Student) { +
-            Student st = (Student) o; +
-            if(firstName.equals(st.firstName) && lastName.equals(st.lastName) && AEM == st.AEM) +
-              return true; +
-          } +
-          return false; +
-        }+
       }       }
     );     );
Line 135: Line 235:
 } }
 </code> </code>
- 
-===== Παράδειγμα - Ανώνυμη εμφωλευμένη κλάση ως επέκταση υφιστάμενης κλάσης ===== 
- 
- 
-Παρακάτω δίνεται ένα άλλο παράδειγμα, όπου η ανώνυμη κλάση επεκτείνει μία υφιστάμενη κλάση αντί για ένα //inteface//. 
- 
-<code java HelloWorldAnonymousClasses.java> 
-public class HelloWorldAnonymousClasses { 
-   
-  interface HelloWorld { 
-    public void greet(); 
-    public void greetSomeone(String someone); 
-  } 
-   
-  public static void sayHello() { 
-     
-    class EnglishGreeting implements HelloWorld { 
-      String name = "world"; 
-      public void greet() { 
-        greetSomeone("world"); 
-      } 
-      public void greetSomeone(String someone) { 
-        name = someone; 
-        System.out.println("Hello " + name); 
-      } 
-    } 
-     
-    HelloWorld englishGreeting = new EnglishGreeting(); 
-     
-    HelloWorld frenchGreeting = new HelloWorld() { 
-      String name = "tout le monde"; 
-      public void greet() { 
-        greetSomeone("tout le monde"); 
-      } 
-      public void greetSomeone(String someone) { 
-        name = someone; 
-        System.out.println("Salut " + name); 
-      } 
-    }; 
-     
-    HelloWorld spanishGreeting = new EnglishGreeting() { 
-      String name = "mundo"; 
-      public void greet() { 
-        greetSomeone("mundo"); 
-      } 
-      public void greetSomeone(String someone) { 
-        name = someone; 
-        System.out.println("Hola, " + name); 
-      } 
-    }; 
-    englishGreeting.greet(); 
-    frenchGreeting.greetSomeone("Fred"); 
-    spanishGreeting.greet(); 
-  } 
- 
-  public static void main(String... args) {     
-    HelloWorldAnonymousClasses.sayHello(); 
-  }       
-} 
-</code> 
- 
-<WRAP tip 80% center round> 
-Παρατηρήστε ότι η μεταβλητή //frenchGreeting// προκύπτει από μία κλάση που υλοποιεί το inteface //HelloWorld// η μεταβλητή //spanishGreeting// προκύπτει ως επέκταση της κλάση //EnglishGreeting//. 
-</WRAP> 
  
 ===== Πρόσβαση στις τοπικές μεταβλητές και στις μεταβλητές της εξωτερικής κλάσης ===== ===== Πρόσβαση στις τοπικές μεταβλητές και στις μεταβλητές της εξωτερικής κλάσης =====
  
-Σε αναλογία με τις [[java:local_inner_classes|τοπικές εμφωλευμένες κλάσεις]] οι ανώνυμες κλάσεις έχουν τις ίδιες δυνατότητες πρόσβασης στις τοπικές μεταβλήτές της μεθόδου στην οποία ορίζονται:+Σε αναλογία με τις [[java:local_inner_classes|τοπικές εμφωλευμένες κλάσεις]] οι ανώνυμες κλάσεις έχουν τις ίδιες δυνατότητες πρόσβασης στις τοπικές μεταβλητές της μεθόδου στην οποία ορίζονται:
   * Η ανώνυμη κλάση έχει πρόσβαση στις μεταβλητές της εξωτερικής κλάσης.   * Η ανώνυμη κλάση έχει πρόσβαση στις μεταβλητές της εξωτερικής κλάσης.
-  * Η ανώνυμη κλάση δεν μπορεί να έχει πρόσβαση σε τοπικές μεταβλητές της μεθόδου στην οποία ορίζονται αν αυτές δεν έχουν δηλωθεί ως //final//.+  * Η ανώνυμη κλάση δεν μπορεί να έχει πρόσβαση σε τοπικές μεταβλητές της μεθόδου στην οποία ορίζεται αν αυτές δεν έχουν δηλωθεί ως //final//.
   * Όπως σε όλες τις μη στατικές εμφωλευμένες κλάσεις ο ορισμός του ίδιου τύπου δεδομένων στην εσωτερική και την εξωτερική κλάση "//κρύβει//" τον συγκεκριμένο τύπο δεδομένων από την εξωτερική κλάση.   * Όπως σε όλες τις μη στατικές εμφωλευμένες κλάσεις ο ορισμός του ίδιου τύπου δεδομένων στην εσωτερική και την εξωτερική κλάση "//κρύβει//" τον συγκεκριμένο τύπο δεδομένων από την εξωτερική κλάση.
-  * Δεν μπορείτε να ορίσετε στατικές μεταβλητές ή μεθόδους μέσα σε μία ανώνυμη κλάση.+  * __Δεν μπορείτε__ να ορίσετε στατικές μεταβλητές ή μεθόδους μέσα σε μία ανώνυμη κλάση.
  
 Σε μία ανώνυμη κλάση μπορείτε να ορίσετε τα εξής: Σε μία ανώνυμη κλάση μπορείτε να ορίσετε τα εξής:
   * Πεδία   * Πεδία
-  * Επιπλέον μεθόδους που δεν ορίζονται στη interface ή στην κλάση που επεκτείνει. +  * Επιπλέον μεθόδους που δεν ορίζονται στο interface ή στην κλάση που επεκτείνεται.
-  * Μεθόδους ή block αρχικοποίησης πεδίων της κλάσης.+
   * Τοπικές κλάσεις που ανήκουν στη ανώνυμη κλάση.   * Τοπικές κλάσεις που ανήκουν στη ανώνυμη κλάση.
   * **ΔΕΝ** μπορείτε και __δεν έχει νόημα__ να ορίσετε κατασκευαστές μέσα σε μία ανώνυμη κλάση.   * **ΔΕΝ** μπορείτε και __δεν έχει νόημα__ να ορίσετε κατασκευαστές μέσα σε μία ανώνυμη κλάση.
  
 | Προηγούμενο : [[ :java:local_inner_classes | Τοπικές εμφωλευμένες κλάσεις   ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο: [[ :java:static_nested_classes | Στατικές εμφωλευμένες κλάσεις  ]]  | | Προηγούμενο : [[ :java:local_inner_classes | Τοπικές εμφωλευμένες κλάσεις   ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο: [[ :java:static_nested_classes | Στατικές εμφωλευμένες κλάσεις  ]]  |
java/anon_inner_classes.txt · Last modified: 2023/03/23 20:43 by gthanos