====== Μη στατικές εμφωλευμένες κλάσεις ====== Οι μη στατικές εμφωλευμένες κλάσεις ή εσωτερικές κλάσεις (inner classes) αποτελούν την γενικότερη περίπτωση εμφώλευσης μίας κλάσης μέσα σε μία άλλη κλάση. Ένας συνήθης λόγος (αλλα όχι ο μοναδικός) για τον οποίο επιδιώκουμε να χρησιμοποιήσουμε εμφωλευμένες κλάσεις είναι όταν θέλουμε να ορίσουμε επιπλέον κλάσεις των οποίων δεν θέλουμε ή δεν έχουμε λόγο να αποκαλύψουμε ότι υπάρχουν. Για παράδειγμα, ας υποθέσουμε ότι θέλουμε να κατασκευάσουμε μία διπλά συνδεδεμένη λίστα η οποία μπορεί να αποθηκεύσει οποιονδήποτε τύπο όμοιων αντικειμένων. Η λίστα θα χρειαστεί να έχει τις βοηθητικές κλάσεις - την κλάση που περιγράφει τον κόμβο της λίστας και - μία κλάση τύπου //iterator// για την διάτρεξη της λίστας Οι δύο παραπάνω κλάσεις εξυπηρετεί να δηλωθούν ως εσωτερικές κλάσεις αποκρύπτοντας την ύπαρξη τους. Ο χρήστης της κλάσης απαιτείται μόνο να γνωρίζει την κλάση της λίστας και πως μπορεί να διαχειριστεί ένα αντικείμενο τύπου [[http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html|java.util.Iterator]]. Όλα τα υπόλοιπα είναι λεπτομέρειες τα οποία δεν αφορούν τον προγραμματιστή-χρήστη της κλάσης. Δείτε τον παρακάτω κώδικα που την υλοποιεί. /* A linked list with sentinels at head and tail. */ public class LinkedList { private Node head, tail; int size; public LinkedList() { head = new Node<>(null, null, null); tail = new Node<>(null, head, null); head.setNext(tail); size = 0; } private class Node { private Node next, prev; private E e; public Node(Node nxt, Node prv, E elem) { next = nxt; prev = prv; e = elem; } public Node getNext() { return next;} public void setNext(Node nxt) { next = nxt; } public Node getPrev() {return prev;} public void setPrev(Node prv) { prev = prv; } public E getElement() { return e; } public void setElement(E elem) { e = elem; } } private class Iterator implements java.util.Iterator { Node curr; public Iterator(Node c) { curr = c; } public boolean hasNext() { if(curr.getNext() != tail) return true; return false; } public E next() { curr = curr.getNext(); return curr.getElement(); } public void remove() { curr.getPrev().setNext(curr.getNext()); curr.getNext().setPrev(curr.getPrev()); curr = curr.getPrev(); } } Iterator iterator() { return new Iterator(head); } // append in the end public boolean add(E elem) { Node plus = new Node(tail, tail.getPrev(), elem); tail.getPrev().setNext(plus); tail.setPrev(plus); size++; return true; } public boolean add(int index, E elem) { if(index>size) return false; Node curr = head.next; for(int i=0; curr != tail && i plus = new Node(curr, curr.prev, elem); curr.prev.next = plus; curr.prev = plus; size++; return true; } public boolean contains(E elem) { Iterator it = iterator(); while(it.hasNext()) { E e = it.next(); if( e.equals(elem) ) return true; } return false; } public int indexOf(E elem) { Iterator it = iterator(); int index = -1; while(it.hasNext()) { E e = it.next(); index++; if( e.equals(elem) ) return index; } return -1; } int size() { return size; } } Το παρακάτω πρόγραμμα επιχειρεί να δημιουργήσει μία λίστα με 20 τυχαίους αριθμούς και στη συνέχεια να τους εκτυπώσει χρησιμοποιώντας τον Iterator της λίστας. Παρατηρήστε ότι σε κανένα σημείου του προγράμματος δεν αποκαλύπτεται η ύπαρξη των εσωτερικών κλάσεων //Node// και //Iterator//. Η μεταβλητή //it// παραπέμπει στο interface [[http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html|java.util.Iterator]]. import java.util.*; public class LinkedListUsage { public static final int SIZE = 16; public static final int RANGE = 8 * SIZE; static void print(LinkedList list){ Iterator it = list.iterator(); // Print list while(it.hasNext()) { System.out.print(it.next()+" "); } System.out.println(); } public static void main(String[] args) { Random rand = new Random( new Date().getTime()); LinkedList list = new LinkedList<>(); for(int i=0; i it = list.iterator(); while(it.hasNext()) { int value = it.next(); //System.out.println("value: "+value); if(value < RANGE/2) { //System.out.println("RMV: "+value); it.remove(); } } print(list); } } **Εργασία για το σπίτι:** Επιχειρήσετε να συμπληρώσετε την κλάση LinkedList ώστε να ικανοποιεί το interface [[http://docs.oracle.com/javase/8/docs/api/java/util/List.html|java.util.List]]. |Προηγούμενο: [[ :java:nested_classes| Εμφωλευμένες κλάσεις ]] | [[:toc|Περιεχόμενα]] |Επόμενο: [[ :java:inner_class_objects | Δημιουργία αντικειμένων της εσωτερικής κλάσης ]]|