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
java:anon_inner_classes [2017/02/06 11:27]
gthanos [Πρόσβαση στις τοπικές μεταβλητές και στις μεταβλητές της εξωτερικής κλάσης]
java:anon_inner_classes [2023/03/23 20:43] (current)
gthanos [Παράδειγμα - Ανώνυμη εμφωλευμένη κλάση ως υλοποίηση ενός interface]
Line 1: Line 1:
 ====== Ανώνυμες εμφωλευμένες κλάσεις ====== ====== Ανώνυμες εμφωλευμένες κλάσεις ======
  
-Οι ανώνυμές εμφωλευμένες κλάσεις επιτρέπουν τον ταυτόχρονο ορισμό της κλάσης και την δημιουργία ενός αντικειμένου, σε μία εντολή. Οι κλάσεις αυτές **ΠΡΕΠΕΙ** **α)** __να υλοποιούν ένα υφιστάμενο interface__ ή **β)** __να επεκτείνουν μία υφιστάμενη κλάση__. Δείτε το παράδειγμα που παρουσιάστηκε στις μη στατικές εμφωλευμένες κλάσεις αλλαγμένο, ώστε να χρησιμοποιεί ανώνυμες κλάσεις.+Οι ανώνυμές εμφωλευμένες κλάσεις επιτρέπουν τον ταυτόχρονο ορισμό της κλάσης και την δημιουργία ενός αντικειμένου, σε μία εντολή. Οι κλάσεις αυτές **ΠΡΕΠΕΙ** **α)** __να υλοποιούν ένα υφιστάμενο interface__ ή **β)** __να επεκτείνουν μία υφιστάμενη κλάση__. 
  
 Ανώνυμες εμφωλευμένες κλάσεις μπορούμε να υλοποιήσουμε όταν συντρέχουν ταυτόχρονα οι παρακάτω λόγοι:  Ανώνυμες εμφωλευμένες κλάσεις μπορούμε να υλοποιήσουμε όταν συντρέχουν ταυτόχρονα οι παρακάτω λόγοι: 
-  - επιθυμούμε την υλοποίηση εσωτερικής κλάσης+  - θέλουμε να υλοποιήσουμε μία εσωτερική κλάση. 
-  - η κλάση αυτή υλοποιεί ένα interface ή επεκτείνει μία άλλη κλάση (η κλάση που επεκτείνεται μπορεί να είναι abstract ή όχι) και  +  - η κλάση αυτή υλοποιεί ένα //interface// ή επεκτείνει μία υφιστάμενη κλάση (η κλάση που επεκτείνεται μπορεί να είναι //abstract// ή όχι) και  
-  - από την κλάση αυτή πρόκειται να δημιουργηθεί μόνο ένα αντικείμενο. +  - από την κλάση αυτή επιθυμούμε να δημιουργηθεί μόνο ένα αντικείμενο. 
    
-Σε αυτές τις περιπτώσεις η χρήση ανώνυμων κλάσεων μπορεί να είναι βολική, καθώς συμπιέζει τον όγκο του κώδικα. Από την πλευρά η εκτεταμένη χρήση ανώνυμων κλάσεων μπορεί να δημιουργήσει κώδικα που είναι δυσανάγνωστος.+Σε αυτές τις περιπτώσεις η χρήση ανώνυμων κλάσεων μπορεί να είναι βολική, καθώς συμπιέζει το μέγεθος του κώδικα. Από την άλλη πλευρά η εκτεταμένη χρήση ανώνυμων κλάσεων μπορεί να δημιουργήσει κώδικα που είναι δυσανάγνωστος.
  
-<code java DataStructure.java> +===== Παράδειγμα - Ανώνυμη εμφωλευμένη κλάση ως υλοποίηση ενός interface ===== 
-public class DataStructure {+ 
 +Στο παρακάτω παράδειγμα ορίζουμε την κλάση **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 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); 
 +  }
      
-  // Create an array +  // First anonymous comparator class 
-  private final static int SIZE = 15; +  static Comparator<Student> lexicographicCmp = new Comparator<Student>() { 
-  private int[] arrayOfInts = new int[SIZE]; +    public int compare(Student st1, Student st2) { 
-   +      int cmp = st1.lastName.compareTo(st2.lastName); 
-  public DataStructure() { +      if(cmp==0) 
-    // fill the array with ascending integer values +        cmp = st1.firstName.compareTo(st2.firstName); 
-    for (int i = 0; i < SIZE; i++{ +      if(cmp==0) 
-      arrayOfInts[i] i;+        cmp = st1.AEM - st2.AEM; 
 +      return cmp;
     }     }
 +  };
 +
 +  public static void sortLexicographically(List<Student> students) {    
 +    Collections.sort(students, Student.lexicographicCmp);
   }   }
      
-  interface DataStructureIterator extends java.util.Iterator<Integer> { } +  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 = 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 
 +5819 Peter Pan 
 +1694 Susan Brown 
 +7895 Lena Smith 
 +3256 Oscar Gonzales 
 +1243 Edgar Wallace 
 +3265 Kate Gordon 
 +4377 Leda Evans 
 +1118 David Lerroy 
 +8744 Amelia Dray 
 +</code> 
 + 
 +<code java SortListOfStudents.java> 
 +import java.io.*; 
 +import java.util.*; 
 + 
 +public class SortListOfStudents {
      
-  public void printEven() { +  public static void readFromFile(List<Student> students, File f) {     
-     +    try(Scanner sc = new Scanner(f)) { 
-    // Print out values of even indices of the array +      while(sc.hasNextLine()) {         
-    DataStructureIterator iterator = new DataStructureIterator() { +        students.add( new Student(sc.nextInt(), sc.next(), sc.next()) );
-      // Start stepping through the array from the beginning +
-      private int nextIndex = 0; +
-     +
-      public boolean hasNext() { +
-         +
-      // Check if the current element is the last in the array +
-      return (nextIndex <= SIZE - 1)+
-      }     +
-     +
-      public Integer next() +
-       +
-      // Record a value of an even index of the array +
-      Integer retValue = Integer.valueOf(arrayOfInts[nextIndex])+
-       +
-      // Get the next even element +
-      nextIndex += 2; +
-      return retValue;+
       }       }
-     
-      public void remove() { } 
-     
-    }; 
-    while (iterator.hasNext()) { 
-      System.out.print(iterator.next() + " "); 
     }     }
-    System.out.println();+    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 void main(String s[]) { +  public static String toString(List<Student> students) { 
-    DataStructure ds = new DataStructure(); +    StringBuilder str = new StringBuilder(); 
-    ds.printEven();+    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> </code>
  
-Παρατηρήστε ότι η ορίζουμε μία νέα κλάση που υλοποιεί το //interface// //DataStructureIterator// χωρίς να δώσουμε όνομα στην νέα κλάση (η κλάση προσδιορίζεται από τον τύπο δεδομένων που ορίζει το //interface//). Παράλληλα με τον ορισμό της κλάσης, δημιουργείται ένα νέο αντικείμενο, στο οποίο δείχνει η μεταβλητή //iterator//. Η συγκεκριμένη κλάση δημιουργήθηκε με βάση το inteface //DataStructureIterator// 
  
-Παρακάτω δίνεται ένα άλλο παράδειγμα, όπου η ανώνυμη κλάση επεκτείνει μία υφιστάμενη κλάση αντί για ένα //inteface//.+===== Παράδειγμα - Ανώνυμη εμφωλευμένη κλάση ως επέκταση υφιστάμενης κλάσης =====
  
-<code java HelloWorldAnonymousClasses.java> +Δείτε το προηγούμενο παράδειγμα παραλλαγμένο ως εξής. Αρχικά φτιάχνουμε την εσωτερική //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**. 
-public class HelloWorldAnonymousClasses {+ 
 +<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); 
 +  }
      
-  interface HelloWorld { +  static abstract class BasicComparator implements Comparator<Student> {
-    public void greet(); +
-    public void greetSomeone(String someone);+
   }   }
 +    
 +  static Comparator<Student> lexicographicCmp = new BasicComparator() {
 +    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 sayHello() {+  public static void sortLexicographically(List<Student> students) {     
 +    Collections.sort(students, lexicographicCmp); 
 +  }
          
-    class EnglishGreeting implements HelloWorld +  public static void sortByAEM(List<Student> students) 
-      String name = "world"; +    Collections.sort(students, new BasicComparator() { 
-      public void greet() { +        public int compare(Student st1, Student st2) { 
-        greetSomeone("world");+          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; 
 +        }        
       }       }
-      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> </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.1486380474.txt.gz · Last modified: 2017/02/06 11:27 by gthanos