Η έννοια της Ενθυλάκωσης (Encapsulation) στην Java αναφέρεται στην τεχνική που χρησιμοποιείται για τη συσκευασία μεθόδων και μεταβλητών μέσα σε ένα αντικείμενο, προκειμένου να περιοριστεί η πρόσβαση σε αυτά από άλλα μέρη του κώδικα.
Στην Java, η ενθυλάκωση επιτυγχάνεται με τη χρήση των access modifiers (προσδιοριστές πρόσβασης) όπως τα private
, public
και protected
. Ορίζοντας τα μέλη ενός αντικειμένου (μεταβλητές ή μεθόδους) ως private
, μπορούμε να περιορίσουμε την πρόσβαση σε αυτά μόνο στο εσωτερικό της κλάσης. Έτσι, τα εξωτερικά μέρη του κώδικα δεν μπορούν να τροποποιήσουν απευθείας τις ιδιότητες του αντικειμένου, αλλά μπορούν να αλληλεπιδρούν μαζί του μέσω δημόσιων (public) μεθόδων.
Η ενθυλάκωση προσφέρει πλεονεκτήματα όπως την προστασία των δεδομένων από ανεπιθύμητες τροποποιήσεις, την καλύτερη οργάνωση και δομή του κώδικα, καθώς και τη δυνατότητα εφαρμογής αλλαγών στην υλοποίηση του αντικειμένου χωρίς να επηρεάζονται οι άλλες μέθοδοι που το χρησιμοποιούν.
Παράδειγμα:
public class Person { private String name; // Ιδιωτική μεταβλητή για το όνομα // Getter public String getName() { return name; // Επιστρέφει το όνομα } // Setter public void setName(String newName) { this.name = newName; // Ορίζει το όνομα } } public class Main { public static void main(String[] args) { Person myObj = new Person(); // Δημιουργεί ένα νέο αντικείμενο της κλάσης Person myObj.setName("John"); // Ορίζει το όνομα του αντικειμένου σε "John" System.out.println(myObj.getName()); // Εκτυπώνει το όνομα του αντικειμένου } }
Ο παραπάνω κώδικας αναπαριστά δύο κλάσεις: την κλάση Person
και την κλάση Main
.
Η κλάση Person
έχει τρεις ιδιωτικές μεταβλητές: name
(τύπου String
), age
(τύπου int
) και address
(τύπου Address
). Υπάρχει ένας δημόσιος κατασκευαστής (constructor) που δέχεται ως ορίσματα τις τιμές για το όνομα, την ηλικία και τη διεύθυνση και τις αποθηκεύει στις αντίστοιχες μεταβλητές. Επίσης, υπάρχουν δημόσιες μέθοδοι getter για την ανάκτηση των τιμών του ονόματος, της ηλικίας και της διεύθυνσης.
Η κλάση Main
περιέχει τη μέθοδο main
, η οποία είναι η εκκίνηση του προγράμματος. Μέσα στη μέθοδο main
δημιουργείται ένα αντικείμενο της κλάσης Person
με όνομα myObj
. Στη συνέχεια, χρησιμοποιείται η μέθοδος setName
για να οριστεί το όνομα του αντικειμένου ως “John”. Τέλος, με τη χρήση της System.out.println
, εμφανίζεται στην οθόνη το όνομα του αντικειμένου, το οποίο παίρνει την τιμή “John”.
Συνολικά, ο κώδικας δημιουργεί ένα αντικείμενο της κλάσης Person
, ορίζει το όνομα του αντι
κειμένου ως “John” και εμφανίζει το όνομα στην οθόνη.
Η ενθυλάκωση (Encapsulation) αποτελεί σημαντική έννοια για την ασφάλεια των δεδομένων. Όταν οι μεταβλητές μιας κλάσης δηλώνονται ως δημόσιες, μπορούν να προσπελαστούν και να τροποποιηθούν άμεσα από άλλες κλάσεις, χωρίς περιορισμούς. Αντίθετα, όταν οι μεταβλητές δηλώνονται ως ιδιωτικές, μόνο οι δημόσιες μέθοδοι μπορούν να έχουν πρόσβαση σε αυτές, γεγονός που διασφαλίζει την ασφάλεια των δεδομένων και επιτρέπει την αποφυγή σφαλμάτων και προβλημάτων. Με αυτόν τον τρόπο, η ενθυλάκωση επιτρέπει την προστασία των δεδομένων από ανεπιθύμητες αλλαγές και επιτρέπει τον έλεγχο της πρόσβασης σε αυτά, προάγοντας την ορθή λειτουργία του προγράμματος και την αποφυγή προβλημάτων στην ανάπτυξη λογισμικού.
Από την προηγούμενη ενότητα μάθαμε ότι οι ιδιωτικές μεταβλητές μπορούν να ανακτηθούν μόνο από την ίδια κλάση, ενώ μια εξωτερική κλάση δεν έχει πρόσβαση σε αυτές. Ωστόσο, μπορούμε να ανακτήσουμε τις ιδιωτικές μεταβλητές αν παρέχουμε δημόσιες μεθόδους get και set.
Η μέθοδος “get” χρησιμοποιείται για να ανακτήσει την τιμή μιας μεταβλητής, ενώ η μέθοδος “set” χρησιμοποιείται για να ορίσει μια τιμή σε μια μεταβλητή.
Παράδειγμα:
public class Person { private String name; // Ιδιωτική μεταβλητή για το όνομα // Getter για το όνομα public String getName() { return name; } // Setter για το όνομα public void setName(String newName) { this.name = newName; } } public class Main { public static void main(String[] args) { Person myObj = new Person(); // Δημιουργία ενός αντικειμένου Person myObj.setName("John"); // Ορίζει την τιμή του ιδιωτικού πεδίου name σε "John" System.out.println(myObj.getName()); // Εμφανίζει την τιμή του ιδιωτικού πεδίου name ("John") } }
Ο παραπάνω κώδικας καθορίζει δύο κλάσεις: την κλάση Person
και την κλάση Main
.
Η κλάση Person
περιέχει ένα ιδιωτικό πεδίο με την ονομασία name
, το οποίο είναι τύπου String
. Επίσης, έχει δύο μέθοδους:
- Η μέθοδος
getName()
επιστρέφει την τιμή του πεδίουname
. - Η μέθοδος
setName()
δέχεται ένα όρισμα τύπουString
και ορίζει την τιμή του πεδίουname
με αυτό το όρισμα.
Η κλάση Main
περιέχει τη μέθοδο main
, η οποία είναι η εκκίνηση του προγράμματος. Μέσα στη μέθοδο main
, γίνονται τα εξής:
- Δημιουργείται ένα νέο αντικείμενο της κλάσης
Person
με τη χρήση του προκαθορισμένου δημιουργού. - Με τη χρήση της μεθόδου
setName()
, ορίζεται η τιμή “John” στο πεδίοname
του αντικειμένου. - Με τη χρήση της μεθόδου
getName()
, εμφανίζεται στην οθόνη η τιμή του πεδίουname
.
Συνολικά, ο κώδικας δημιουργεί ένα αντικείμενο τύπου Person
, ορίζει το όνομα του ατόμου ως “John” και εμφανίζει το όνομα αυτό στην οθόνη.
[adinserter block=”2″]
Με αυτόν τον τρόπο, η ιδιωτική μεταβλητή name προστατεύεται από άλλες κλάσεις και μπορεί να τροποποιηθεί μόνο μέσω των δημόσιων μεθόδων getName() και setName().
Ωστόσο, επειδή η μεταβλητή name δηλώνεται ως ιδιωτική, δεν μπορούμε να την προσπελάσουμε από άλλες κλάσεις:
public class Main { public static void main(String[] args) { Person myObj = new Person(); myObj.name = "John"; // ΠΡΟΣΟΧΗ: Αυτό θα οδηγήσει σε σφάλμα System.out.println(myObj.name); // ΠΡΟΣΟΧΗ: Αυτό θα οδηγήσει σε σφάλμα } }
Στο παραπάνω παράδειγμα, η κλάση Main δημιουργεί ένα αντικείμενο της κλάσης Person, αλλά δεν μπορεί να προσπελάσει την ιδιωτική μεταβλητή name μέσω του αντικειμένου, επειδή δεν είναι προσβάσιμη σε άλλες κλάσεις.
Για να ανακτήσουμε ή να αλλάξουμε την τιμή της ιδιωτικής μεταβλητής name από άλλες κλάσεις, πρέπει να χρησιμοποιήσουμε τις δημόσιες μεθόδους getName() και setName() που παρέχει η κλάση Person.
Αντ’ αυτού, χρησιμοποιούμε τις μεθόδους getName() και setName() για να ανακτήσουμε και να αλλάξουμε την τιμή της μεταβλητής:
public class Main { public static void main(String[] args) { Person myObj = new Person(); myObj.setName("John"); System.out.println(myObj.getName()); } }
Στο παραπάνω παράδειγμα, χρησιμοποιούμε τη μέθοδο setName() για να ορίσουμε την τιμή της μεταβλητής name στο αντικείμενο myObj της κλάσης Person ως “John”. Στη συνέχεια, χρησιμοποιούμε τη μέθοδο getName() για να επιστρέψουμε την τιμή της ίδιας μεταβλητής ως “John”.
Τα πλεονεκτήματα της ενθυλάκωσης είναι τα εξής:
- Καλύτερος έλεγχος των γνωρισμάτων και των μεθόδων της κλάσης
- Τα γνωρίσματα της κλάσης μπορούν να γίνουν μόνο αναγνώσιμα (εάν χρησιμοποιείται μόνο η μέθοδος get) ή μόνο εγγράψιμα (εάν χρησιμοποιείται μόνο η μέθοδος set)
- Ευέλικτο: ο προγραμματιστής μπορεί να αλλάξει ένα μέρος του κώδικα χωρίς να επηρεάζει άλλα μέρη
- Αυξημένη ασφάλεια των δεδομένων: τα δεδομένα είναι κρυπτογραφημένα και προστατεύονται από άλλες κλάσεις.
Επίσης, η ενθυλάκωση βοηθάει στη διατήρηση μιας καλύτερης οργάνωσης του κώδικα, καθώς οι μέθοδοι που αλληλεπιδρούν με ένα γνώρισμα της κλάσης βρίσκονται συγκεντρωμένες στο ίδιο αντικείμενο. Αυτό καθιστά πιο εύκολο τον εντοπισμό και τη διόρθωση σφαλμάτων καθώς και την ανάπτυξη νέων χαρακτηριστικών.