2.5 Εμφωλευμένες κλάσεις στην Java

Στην Java, ο όρος “εμφωλευμένες κλάσεις” αναφέρεται στη δυνατότητα να δημιουργήσουμε μια κλάση μέσα στο εσωτερικό μιας άλλης κλάσης. Αυτή η τεχνική ονομάζεται εμφωλευμένες κλάσεις ή εσωτερικές κλάσεις.

Οι εμφωλευμένες κλάσεις μας επιτρέπουν να οργανώσουμε τον κώδικά μας και να αυξήσουμε την ασφάλεια και τη συντήρηση του. Μια εμφωλευμένη κλάση έχει πρόσβαση σε όλα τα μέλη (μεταβλητές, μέθοδοι) της εξωτερικής κλάσης, συμπεριλαμβανομένων των ιδιωτικών μελών της.

Οι εμφωλευμένες κλάσεις μπορούν να χρησιμοποιηθούν για την οργάνωση του κώδικα, την υλοποίηση λειτουργικοτήτων που αφορούν μόνο την εξωτερική κλάση, και την επίτευξη μιας καθαρής και συμπαγούς δομής κώδικα.

Για να έχετε πρόσβαση στην εσωτερική κλάση, δημιουργήστε ένα αντικείμενο της εξωτερικής κλάσης και στη συνέχεια δημιουργήστε ένα αντικείμενο της εσωτερικής κλάσης:

// Αυτή είναι μια κλάση OuterClass
class OuterClass {
  int x = 10;

  // Αυτή είναι μια εσωτερική κλάση InnerClass
  class InnerClass {
    int y = 5;
  }
}

public class Main {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();  // Δημιουργία αντικειμένου OuterClass
    OuterClass.InnerClass myInner = myOuter.new InnerClass();  // Δημιουργία αντικειμένου InnerClass
    System.out.println(myInner.y + myOuter.x);  // Εμφάνιση της τιμής x και y
  }
}

Ο παραπάνω κώδικας δημιουργεί δύο κλάσεις, την OuterClass και την InnerClass. Η OuterClass είναι μια εξωτερική κλάση, ενώ η InnerClass είναι μια εσωτερική κλάση που βρίσκεται μέσα στην OuterClass.

Η OuterClass περιέχει ένα πεδίο x με τιμή 10. Η InnerClass περιέχει ένα πεδίο y με τιμή 5.

Στην Main κλάση, στην μέθοδο main, δημιουργείται ένα αντικείμενο myOuter της κλάσης OuterClass. Έπειτα, δημιουργείται ένα αντικείμενο myInner της κλάσης InnerClass μέσα από το myOuter αντικείμενο. Τελικά, εκτυπώνεται η τιμή του πεδίου y του myInner αντικειμένου προσθέτοντας την τιμή του πεδίου x του myOuter αντικειμένου.

Συνολικά, ο κώδικας εμφανίζει το αποτέλεσμα της πρόσθεσης των τιμών των πεδίων x και y, δηλαδή 15, στην οθόνη.

Εσωτερικές κλάσεις μπορούν να χρησιμοποιηθούν και για να κάνουν τον κώδικα πιο ασφαλή ή οργανωμένο. Ένα ακόμη παράδειγμα είναι η χρήση των private εσωτερικών κλάσεων για την προστασία ευαίσθητων δεδομένων από τις εξωτερικές κλάσεις.

Σε αντίθεση με μια “κανονική” κλάση, μια εσωτερική κλάση μπορεί να είναι ιδιωτική ή προστατευμένη. Αν δεν θέλετε αντικείμενα από το εξωτερικό να έχουν πρόσβαση στην εσωτερική κλάση, δηλώστε την κλάση ως ιδιωτική:

class OuterClass {
  int x = 10; // Μια μεταβλητή x στην εξωτερική κλάση OuterClass

  private class InnerClass {
    int y = 5; // Μια μεταβλητή y στην ιδιωτική εσωτερική κλάση InnerClass
  }
}

public class Main {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    // Δεν είναι δυνατή η δημιουργία αντικειμένου για την ιδιωτική εσωτερική κλάση
    // OuterClass.InnerClass myInner = myOuter.new InnerClass();
  }
}

Ο παραπάνω κώδικας περιέχει δύο κλάσεις, την OuterClass και την Main. Ας τις αναλύσουμε μία προς μία:

  1. OuterClass: Αυτή η κλάση έχει ένα πεδίο x τύπου int με τιμή 10. Το πεδίο αυτό είναι προσβάσιμο από οποιαδήποτε μέθοδο της κλάσης OuterClass.
  2. Main: Αυτή η κλάση περιέχει τη μέθοδο main, η οποία είναι η εκκίνηση του προγράμματος. Μέσα στην main δημιουργείται ένα αντικείμενο της OuterClass με το όνομα myOuter.

Σημειώνεται ότι υπάρχει και η ιδιωτική εσωτερική κλάση InnerClass μέσα στην OuterClass, αλλά η προσπέλαση της δημιουργίας αντικειμένου αυτής της κλάσης από την Main κλάση έχει σχολιαστεί, δηλαδή έχει απενεργοποιηθεί με τη χρήση σχόλιων.

Αν προσπαθήσετε να έχετε πρόσβαση σε μια ιδιωτική εσωτερική κλάση από μια κλάση εκτός της θυγατρικής κλάσης, θα προκληθεί σφάλμα κατά τη διάρκεια του χρόνου εκτέλεσης (runtime error):

class OuterClass {
  int x = 10;

  private class InnerClass {
    int y = 5;
  }
}

public class Main {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    // Δεν είναι δυνατή η δημιουργία αντικειμένου για την ιδιωτική εσωτερική κλάση
    // OuterClass.InnerClass myInner = myOuter.new InnerClass();
  }
}

class AnotherClass {
  // Αυτό προκαλεί σφάλμα κατά τη διάρκεια της εκτέλεσης
  // OuterClass.InnerClass myInner = new OuterClass().new InnerClass();
}

Στο παραπάνω παράδειγμα, η InnerClass είναι ιδιωτική και προσπαθούμε να δημιουργήσουμε ένα αντικείμενο της από μια άλλη κλάση. Αυτό θα προκαλέσει ένα runtime error.

Το σφάλμα που θα λάβετε στο προηγούμενο παράδειγμα είναι το εξής:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    The type OuterClass.InnerClass is not visible

    at AnotherClass.<init>(AnotherClass.java:3)
    at Main.main(Main.java:14)

Η αιτία του σφάλματος είναι ότι η ιδιωτική εσωτερική κλάση InnerClass δεν είναι ορατή από άλλες κλάσεις εκτός από την OuterClass.

Μια εσωτερική κλάση μπορεί επίσης να είναι στατική (static), το οποίο σημαίνει ότι μπορείτε να έχετε πρόσβαση σε αυτήν χωρίς να δημιουργήσετε ένα αντικείμενο της εξωτερικής κλάσης:

class OuterClass {
  int x = 10;

  static class InnerClass {
    int y = 5;
  }
}

public class Main {
  public static void main(String[] args) {
    // Δεν χρειάζεται να δημιουργήσετε ένα αντικείμενο της εξωτερικής κλάσης για να έχετε πρόσβαση στη στατική εσωτερική κλάση
    OuterClass.InnerClass myInner = new OuterClass.InnerClass();
    System.out.println(myInner.y);
  }
}

Στο παραπάνω παράδειγμα, η εσωτερική κλάση InnerClass είναι στατική. Αυτό σημαίνει ότι μπορείτε να έχετε πρόσβαση σε αυτήν χωρίς να χρειάζεται να δημιουργήσετε ένα αντικείμενο της εξωτερικής κλάσης OuterClass.

Ένα από τα πλεονεκτήματα των εσωτερικών κλάσεων είναι ότι μπορούν να έχουν πρόσβαση στα χαρακτηριστικά και τις μεθόδους της εξωτερικής κλάσης:

class OuterClass {
  int x = 10; // Μια μεταβλητή τύπου int με την τιμή 10

  class InnerClass {
    public int myInnerMethod() {
      return x; // Επιστρέφει την τιμή της μεταβλητής x από την εξωτερική κλάση
    }
  }
}

public class Main {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass(); // Δημιουργία ενός αντικειμένου της εξωτερικής κλάσης
    OuterClass.InnerClass myInner = myOuter.new InnerClass(); // Δημιουργία ενός αντικειμένου της εσωτερικής κλάσης
    System.out.println(myInner.myInnerMethod()); // Εκτύπωση της τιμής που επιστρέφει η μέθοδος myInnerMethod()
  }
}

Στο παραπάνω παράδειγμα, η εσωτερική κλάση InnerClass έχει πρόσβαση στη μεταβλητή x της εξωτερικής κλάσης OuterClass. Μέσω της δημιουργίας ενός αντικειμένου της OuterClass και του ακόλουθου δημιουργίας ενός αντικειμένου της InnerClass, μπορούμε να καλέσουμε τη μέθοδο myInnerMethod() και να επιστρέψουμε την τιμή της μεταβλητής x.

Το παραπάνω παράδειγμα θα εμφανίσει το ακόλουθο αποτέλεσμα:

10

Στη μέθοδο main(), δημιουργούμε ένα αντικείμενο της OuterClass και ένα αντικείμενο της InnerClass. Στη συνέχεια, καλούμε τη μέθοδο myInnerMethod() στο αντικείμενο της InnerClass, η οποία επιστρέφει την τιμή της μεταβλητής x της εξωτερικής κλάσης. Τέλος, εκτυπώνουμε την τιμή που επιστρέφει η μέθοδος myInnerMethod(), η οποία είναι 10.

14 Ιουνίου, 2023
top
error: Content is protected !!
Μετάβαση σε γραμμή εργαλείων