C# COMPLETE COURSE
ΕΝΟΤΗΤΑ 14 - FIELD ACCESS MODIFIERS
INTRODUCTION
Σε αυτό το δωρεάν μάθημα C# θα δούμε πως ακριβώς οι Access Modifiers (όπως private, internal, και public) επηρεάζουν την πρόσβαση στα fields μιας κλάσης όταν προσπαθούμε να αποκτήσουμε πρόσβαση σε αυτά είτε από άλλες κλάσεις που ανήκουν στο ίδιο project είτε από κλάσεις που ανήκουν σε διαφορετικά projects του ίδιου solution.
ADDING A NEW PROJECT TO AN EXISTING SOLUTION
Στο solution, που είχαμε δημιουργήσει στο προηγούμενο δωρεάν μάθημα C#, προσθέσαμε ένα project με το όνομα ClassAndFields μέσα στο οποίο δημιουργήσαμε δύο κλάσεις - την Product και την Program.
Έχουμε την δυνατότητα μέσα σε ένα solution να έχουμε περισσότερα από ένα project. Συνήθως το κάθε project περιγράφει μια αυτόνομη λειτουργία ή απλά κλάσεις που μπορούν να χρησιμοποιηθούν σαν βιβλιοθήκες για τα υπόλοιπα projects έτσι ώστε να μην επαναλαμβάνουμε να γράφουμε τον ίδιο κώδικα συνέχεια.
Στο δικό μας παράδειγμα, θα δημιουργήσουμε ένα ακόμα project, μέσα στο ίδιο solution, στο οποίο θα μεταφέρουμε την κλάση Product. Η τελική δομή του project θα είναι να περιέχει ένα project με την κλάση Program και ένα δεύτερο project με την κλάση Pρoduct. Αυτή η δομή θα μας βοηθήσει να κατανοήσουμε καλύτερα πως οι access modifiers που θα ορίσουμε θα επηρεάζουν κάθε φορά την πρόσβαση στα fields της Product. Ας δούμε όμως την διαδικασία από την αρχή εξηγώντας κάθε βήμα ξεχωριστά όπως το εκτελούμε.
Για αρχή, κάνουμε δεξί κλικ επάνω στο solution και από το εμφανιζόμενο μενού επιλέγουμε Add --> New Project...
Από τα project templates επιλέγουμε το Class Library. Αυτό το είδος του project μπορεί να περιέχει κλάσεις που θα χρησιμοποιηθούν από τα υπόλοιπα projects του solution. Αφού το επιλέξετε πατήστε Next.
Στο επόμενο βήμα θα πρέπει να δηλώσετε ένα όνομα για το καινούργιο project. Επειδή το παράδειγμα μας είναι απλό, μπορούμε κάλλιστα να δεχτούμε το όνομα που προτείνει το Visual Studio δηλαδή ClassLibrary1. Αφού ορίσετε και τον φάκελο στο σκληρό σας δίσκο που θα αποθηκευτεί το project πατήστε Next.
Ας μην ξεχνάμε ότι όλα μας τα παραδείγματα τα έχουμε δημιουργήσει γράφοντας κώδικα στην έκδοση .NET 8.0. Οπότε βεβαιωθείτε ότι και το καινούργιο project χρησιμοποιεί την ίδια έκδοση του .NET έτσι ώστε να αποφύγουμε τυχόν λάθη συμβατότητας. Πατήστε Create για να δημιουργηθεί το καινούργιο project.
Μπορείτε τώρα να κάνετε copy την κλάση Product από το project ClassAndFields και paste μέσα στο project ClassLibrary1. Όταν το πετύχετε αυτό διαγράψτε την αρχική κλάση Product από το ClassAndFields project και επίσης διαγράψτε την άδεια κλάση Class1 που δημιουργήθηκε αυτόματα με την δημιουργία του project. Η τελική μορφή του solution θα είναι τώρα η εξής:
Αν ανοίξουμε τον κώδικα του Program θα παρατηρήσουμε αμέσως ότι οι γραμμές κώδικα οι οποίες δημιουργούν τα αντικείμενα product1 και product2 παρουσιάζουν λάθη. Στην πραγματικότητα είναι το ίδιο λάθος που επαναλαμβάνεται και μας ενημερώνει ότι δεν μπορεί να βρεθεί η κλάση Product για να προχωρήσει η δημιουργία των αντικειμένων.
Αν και τα δύο projects βρίσκονται μέσα στο ίδιο solution αυτό δεν σημαίνει ότι αυτόματα το ένα project θα έχει πρόσβαση στα στοιχεία του άλλου project. Για να αποκτήσουμε αυτή τη δυνατότητα και να εξαλειφθούν τα λάθη, θα πρέπει να ορίσουμε εμείς ότι το project ClassAndFields εξαρτάται από κλάσεις που βρίσκονται στο project ClassLibrary1.
Κάνουμε δεξί κλικ επάνω στο Dependencies του ClassAndFields project και από το εμφανιζόμενο μενού επιλέγουμε Add Project Reference.
Στο παράθυρο που θα εμφανιστεί τσεκάρετε το ClassLibrary1 και πατάτε ΟΚ. Με αυτό το τρόπο έχουμε δηλώσει ότι όποτε χρειαστεί το project ClassAndFields να δημιουργήσει αντικείμενα είδος Product τότε θα ψάξει στο ClassLibrary1 project.
Αν κοιτάξετε τώρα τον κώδικα του Program θα δείτε ότι δεν υπάρχουν πια λάθη και ότι το πρόγραμμα μας εκτελείτε και πάλι κανονικά.
ACCESS MODIFIERS
Σαν access modifiers ορίζουμε τις λέξεις κλειδιά που προσθέτουμε πριν τον ορισμό του ονόματος των μεταβλητών, των μεθόδων ή των κλάσεων για να ορίσουμε ακριβώς το είδος πρόσβασης που θα έχουν σε αυτά άλλα στοιχεία του solution. Σε αυτό το δωρεάν μάθημα C# θα αναφερθούμε μόνο στα access modifiers που ορίζονται μπροστά από μεταβλητές (fields). Σε μελλοντικά δωρεάν μαθήματα C# θα έχουμε την ευκαιρία να χρησιμοποιήσουμε τα access modifiers και σε μεθόδους όπως και σε κλάσεις.
Στο παράδειγμα μας, έχουμε ορίσει όλα τα fields της κλάσης Product να έχουν οριστεί με το public access modifier. Αυτή η δήλωση επιτρέπει, με βάση τον παρακάτω πίνακα που μας προσφέρει το documentation της C#, οποιαδήποτε άλλο στοιχείο του solution να έχει πρόσβαση στα fields της κλάσης Product.
PUBLIC ACCESS MODIFIERS
Δεν θα καλύψουμε όλες τις περιπτώσεις του πίνακα γιατί πολύ απλά από την στιγμή που καταλάβετε τον μηχανισμό θα μπορείτε να εφαρμόζετε την κατάλληλη λογική στο πρόγραμμα σας. Ας ξεκινήσουμε από την πιο απλή περίπτωση που είναι ο public access modifier.
Στην κλάση Product όλα τα fields έχουν οριστεί με public access. Αυτό σημαίνει, με βάση τον πίνακα, ότι οποιαδήποτε άλλη κλάση από οποιοδήποτε άλλο project θα μπορεί, αφού δημιουργήσει αντικείμενο, να έχει πρόσβαση σε αυτά τα fields.
Όταν ερχόμαστε τώρα να δημιουργήσουμε αντικείμενα είδος Product από την Program, αφού δημιουργήσουμε το αντικείμενα και γράψουμε την τελεία θα δούμε ότι εμφανίζεται μια λίστα με όλα τα διαθέσιμα fieds.
PRIVATE ACCESS MODIFIERS
Πολύ συχνά, ή καλύτερα σχεδόν πάντα, θα χρησιμοποιείτε τον private access modifier στα fields. Τον λόγο θα τον καταλάβετε απόλυτα σε μελλοντικό δωρεάν μάθημα C# όταν μιλήσουμε για τις μεθόδους. Για τώρα απλά μας αρκεί να γνωρίζουμε ότι ορίζοντας private το είδος πρόσβασης στα fields περιορίζουμε όσο το δυνατόν γίνεται την πιθανότητα ανάθεσης λάθος τιμής στην μεταβλητή. Με άλλα λόγια προστατεύουμε την μεταβλητή από ανάθεση λάθων τιμών σε αυτή.
Με βάση λοιπόν τον πίνακα, όποιο field έχει οριστεί σαν private, μόνο στοιχεία μέσα από το ίδιο αρχείο ή την ίδια κλάση μπορούν να έχουν πρόσβαση σε αυτό. Τι σημαίνει όμως αυτό;
Ας πάμε πίσω στην κλάση Product και ας αλλάξουμε το public σε private για το field productName. Αμέσως μετά από αυτή την αλλαγή θα παρατηρήσουμε ότι ο κώδικα στο Program παρουσιάζει λάθη γιατί δεν μπορεί να βρεθεί η μεταβλητή productName.
Εδώ η εξήγηση είναι πολύ απλή - μια κλάση με το όνομα Program από ένα διαφορετικό project, αφού δημιουργήσει ένα αντικείμενο από την κλάση Product προσπαθεί να αποκτήσει πρόσβαση στα fields της κλάσης. Όμως το field productName επιτρέπει την πρόσβαση σε αυτό μόνο σε κάποιο άλλο στοιχείο που είναι μέσα στην ίδια κλάση.
Για να το επιβεβαιώσουμε αυτό, μπορούμε να δημιουργήσουμε μια πολύ απλή μέθοδο μέσα στην κλάση Product που θα έχει σκοπό να διαβάζει απλά την τιμή της μεταβλητής productName και να τη δείχνει στο terminal. Δεν έχουμε καλύψει ακόμα την θεωρία για τις μεθόδους οπότε μην συγκεντρωθείτε στο πως ακριβώς λειτουργούν. Αυτό που μόνο μας ενδιαφέρει για τώρα είναι το γεγονός ότι ένα άλλο στοιχείο μέσα από την ίδια κλάση μπορεί να έχει πρόσβαση σε private fields. Ας προσθέσουμε μια μέθοδο μέσα στην κλάση Product.
Όπως βλέπετε, η μέθοδο που βρίσκεται μέσα στην ίδια κλάση, μπορεί να διαβάσει το field productName. Φυσικά για να τρέξει το πρόγραμμα μας χρειάζονται να γίνουν και άλλες αλλαγές, που ακόμα δεν γνωρίζουμε σαν θεωρία. Για τώρα απλά συγκεντρωνόμαστε στα access modifiers και τι σημαίνουν οι διάφοροι ορισμοί που βρίσκονται στο documentation της C#.
PROTECTED ACCESS MODIFIERS
Αν αναφερθούμε για ακόμα μια φορά στο πίνακα, θα δούμε ότι το protected access modifier επιτρέπει την πρόσβαση σε ένα field εφόσον το άλλο στοιχείο βρίσκεται μέσα στην ίδια κλάση, έχει κληρονομήσει από την αρχική κλάση μέσα στο ίδιο project ή έχει κληρονομηκότητα με την αρχική κλάση αλλά βρίσκεται σε διαφορετικό project. Πάμε λοιπόν να δούμε αυτές τις περιπτώσεις.
Για αρχή ας αλλάξουμε το private σε protected για το field productName. Θα δούμε ότι ακόμα η μέθοδο έχει κανονικά πρόσβαση στο field.
Τώρα ας δημιουργήσουμε μια ακόμα κλάση μέσα στο ίδιο αρχείο με το όνομα DomesticProduct η οποία κληρονομεί από την Product. Η κληρονομικότητα ορίζεται στη C# από το colon ( : ) και το όνομα της κλάσης από την οποία κληρονομούμε. Η απλή λογική της κληρονομικότητας είναι ότι δεν χρειάζεται να ορίσουμε ξανά στοιχεία που έχουν οριστεί ήδη σε μια κλάση. Απλά τα κληρονομούμε και τα χρησιμοποιούμε προσθέτοντας ίσως και κάποια επιπλέον στοιχεία. Έτσι αποφεύγουμε να επαναλαμβάνουμε τον ίδιο κώδικα και ορισμούς μέσα στο πρόγραμμα μας. Για ακόμη μια φορά αναφέρω το γεγονός ότι δεν έχουμε καλύψει την κληρονομικότητα ακόμα στα μαθήματα μας. Απλά εδώ την χρησιμοποιούμε για να καταλάβουμε τους access specifiers.
Πάμε τώρα να επιβεβαιώσουμε και το γεγονός ότι αν υπάρχει κληρονομικότητα από μια κλάση που βρίσκεται σε διαφορετικό project, πάλι θα έχουμε πρόσβαση στην protected μεταβλητή. Δημιουργούμε λοιπόν μέσα στo project ClassAndFields μια επιπλέον κλάση με το όνομα InternationalProduct η οποία κληρονομεί από την Product.
Όπως βλέπουμε ο κώδικας της κλάση InternationalProduct δεν παρουσιάζει κανένα λάθος και έχει πρόσβαση, μέσω της μεθόδου, στο field productName της κλάσης Product. Αν όμως δεν κληρονομούσε από την Product τότε δεν θα μπορούσε να έχει πρόσβαση στο productName.
PRIVATE PROTECTED ACCESS MODIFIERS
Εδώ συνδιάζονται το private και το protected access modifier για να δημιουργήσουν ένα είδος πρόσβασης που μας επιτρέπει πρόσβαση στο field μόνο όταν είσαι στην ίδια κλάση (λογική private) ή έχει κληρονομήσει από την κλάση αλλά βρίσκεσαι μέσα στο ίδιο project. Οπότε τώρα δεν μπορούμε από διαφορετικό project, άσχετα αν κληρονομούμε από την κλάση Product ή όχι, να έχουμε πρόσβαση στο productName.
Ας αλλάξουμε λοιπόν το access modifer του productName σε private protected και ας δούμε πως συμπεριφέρονται οι δύο κλάσεις οι οποίες κληρονομούν από την Product.
INTERNAL ACCESS MODIFIERS
Με το internal δίνουμε πρόσβαση στο productName από οπουδήποτε μέσα στο ίδιο project ασχέτως αν υπάρχει κληρονομικότητα ή όχι από την κλάση Product.
Τους access modifiers θα τους χρησιμοποιούμε συνέχεια σε κάθε πρόγραμμα που θα δημιουργούμε. Αυτή ήταν μια πρώτη επαφή για να καταλάβετε πως λειτουργούν χωρίς όμως να αναλύσουμε την θεωρία των μεθόδων ή της κληρονομικότητας. Όταν προσθέσουμε και αυτή τη θεωρία τότε θα καταλάβετε απόλυτα πόσο χρήσιμο και σημαντικό είναι να δηλώνετε τους σωστούς access modifiers.
ΕΙΣΗΓΗΤΗΣ
Μιχάλης Κασάπογλου
Ο Μιχάλης Κασάπογλου, είναι ένας από τους πιο έμπειρους τεχνικούς εκπαιδευτές στον χώρο του προγραμματισμού με πάνω από 20 χρόνια εμπειρία. Έχει εργαστεί σαν IT Operations Manager, Senior Programmer, και Training Team Leader ενώ κατέχει και αρκετές πιστοποιήσεις που καλύπτουν ένα μεγάλο φάσμα τεχνολογιών στο προγραμματισμό, σε βάσεις δεδομένων και cloud. Στον ελεύθερο του χρόνο διατηρεί ένα τεχνολογικό blog στο οποίο θα βρείτε αρκετά δωρεάν μαθήματα προγραμματισμού για αρχάριους.