# Βαθμωτά με tie Ένα βαθμωτό με tie είναι η μικρότερη διεπαφή tie και το καλύτερο μέρος για να μάθετε τη μορφή όλων των υπολοίπων. Ορίζετε έναν κατασκευαστή και δύο μεθόδους προσπέλασης· από εκεί και πέρα, κάθε ανάγνωση της μεταβλητής καλεί τη μία και κάθε εγγραφή καλεί την άλλη. Η κλάση χρειάζεται τέσσερις μεθόδους, οι δύο από τις οποίες είναι προαιρετικές: - `TIESCALAR` - ο κατασκευαστής, που καλείται μία φορά από το [`tie`](../../p5/core/perlfunc/tie.md). - `FETCH` - καλείται σε κάθε ανάγνωση της μεταβλητής. - `STORE` - καλείται σε κάθε εγγραφή στη μεταβλητή. - `DESTROY` - καλείται όταν η μεταβλητή με tie παύει να υπάρχει (προαιρετική). Η πλήρης λίστα υπογραφών βρίσκεται στη σελίδα αναφοράς του [`tie`](../../p5/core/perlfunc/tie.md). Αυτό το κεφάλαιο δείχνει τι κάνει κάθε μέθοδος φτιάχνοντας μία. ## Μια πλήρης κλάση Ένας μετρητής που περικόπτει τις εγγραφές ώστε η τιμή να μην πέφτει ποτέ κάτω από το μηδέν: ```perl use v5.36; package Counter { sub TIESCALAR { my ($class, $start) = @_; my $n = $start // 0; return bless \$n, $class; } sub FETCH { my $self = shift; return $$self } sub STORE { my ($self, $value) = @_; $$self = $value < 0 ? 0 : $value; # never go below zero } sub DESTROY { } } tie my $hits, 'Counter', 10; say $hits; # 10 $hits = 25; say $hits; # 25 $hits = -7; say $hits; # 0 ``` Το αντικείμενο πίσω από το βαθμωτό μπορεί να είναι οτιδήποτε blessed - εδώ μια αναφορά σε έναν απλό αριθμό. Η `LIST` μετά το όνομα της κλάσης στην κλήση `tie` (`10`) περνά κατευθείαν στο `TIESCALAR`. ## Το συμβόλαιο των μεθόδων `TIESCALAR classname, LIST` : Ο κατασκευαστής. Λαμβάνει το όνομα της κλάσης και όποια επιπλέον ορίσματα πέρασαν στο `tie`. Πρέπει να επιστρέψει μια blessed αναφορά· αυτή η αναφορά γίνεται το αντικείμενο με tie και η τιμή επιστροφής της κλήσης `tie`. Μια συνηθισμένη συντόμευση είναι μια blessed αναφορά βαθμωτού που κρατά την τιμή, όπως παραπάνω, αλλά μια blessed αναφορά hash είναι εξίσου έγκυρη όταν η κλάση χρειάζεται περισσότερη κατάσταση. `FETCH this` : Καλείται κάθε φορά που η μεταβλητή διαβάζεται. Δέχεται μόνο το αντικείμενο. Ό,τι επιστρέφει είναι αυτό που βλέπει ο αναγνώστης. Το `FETCH` είναι το σημείο όπου ένα υπολογιζόμενο βαθμωτό αξίζει τον κόπο: μπορεί να επαναϋπολογίσει, να αναζητήσει κάτι, ή να καταγράψει την προσπέλαση και να επιστρέψει μια αποθηκευμένη τιμή. `STORE this, value` : Καλείται κάθε φορά που γίνεται ανάθεση στη μεταβλητή. Λαμβάνει το αντικείμενο και τη μοναδική νέα τιμή. Η τιμή επιστροφής της αγνοείται - η τιμή της έκφρασης ανάθεσης προέρχεται από ένα επακόλουθο `FETCH`, όχι από το `STORE`. Εδώ ζει η επικύρωση, η περικοπή ή η εγγραφή προς έναν υποκείμενο αποθηκευτικό χώρο. `DESTROY this` : Καλείται όταν η μεταβλητή με tie καταστρέφεται (έξοδος από εμβέλεια, ή πτώση της τελευταίας αναφοράς). Ορίστε την μόνο όταν η κλάση κρατά έναν πόρο που χρειάζεται απελευθέρωση - ένα ανοιχτό handle, ένα κλείδωμα. Ένας μετρητής δεν έχει τίποτα να καθαρίσει, οπότε το `DESTROY` του είναι κενό ή παραλείπεται εντελώς. ## Χρονισμός κλήσεων - Η ανάγνωση σε οποιοδήποτε περιβάλλον καλεί το `FETCH`. Τα `say $hits`, `$x = $hits + 1` και `"$hits"` πυροδοτούν το καθένα ένα `FETCH`. - Η ανάθεση καλεί το `STORE` με την τιμή του δεξιού μέλους. Το `$hits = 25` καλεί `STORE($obj, 25)`. - Η σύνθετη ανάθεση πρώτα διαβάζει και μετά γράφει: το `$hits += 5` καλεί `FETCH`, προσθέτει 5, και μετά `STORE`. Το ίδιο κάνει και το `$hits++`. - Η τιμή μιας έκφρασης ανάθεσης προέρχεται από το `FETCH`, όχι από την τιμή επιστροφής του `STORE`. Μετά το `my $r = ($hits = -7)`, το `$r` είναι `0` επειδή η περικοπή έτρεξε στο `STORE` και η τιμή της έκφρασης ανακτήθηκε εκ νέου. ## Ελάχιστη βιώσιμη κλάση Το μικρότερο χρήσιμο βαθμωτό με tie ορίζει ακριβώς τα `TIESCALAR`, `FETCH` και `STORE`. Παραλείψτε το `DESTROY` εκτός αν δεσμεύετε κάτι. Μια κλάση με μόνο `TIESCALAR` και `FETCH` παράγει ένα βαθμωτό μόνο για ανάγνωση: το tie γίνεται κανονικά, αλλά η πρώτη ανάθεση πεθαίνει με `Can't locate object method "STORE"`. ## Ο εύκολος τρόπος: κληρονομήστε από το `Tie::StdScalar` Το `Tie::StdScalar` (που συνοδεύει το `Tie::Scalar`) υλοποιεί τα `TIESCALAR`, `FETCH`, `STORE` και `DESTROY` πάνω σε μια blessed αναφορά βαθμωτού. Κληρονομήστε από αυτό και υπερκαλύψτε μόνο το hook που θέλετε να αλλάξετε: ```perl package Uppercase { use Tie::Scalar; our @ISA = ('Tie::StdScalar'); sub STORE { my ($self, $v) = @_; $$self = uc $v } } tie my $shout, 'Uppercase'; $shout = 'hello'; say $shout; # HELLO ``` Το `STORE` μετατρέπει σε κεφαλαία κατά την είσοδο· το `FETCH` και ο κατασκευαστής προέρχονται από τη βασική κλάση αμετάβλητα. Το ίδιο το `Tie::Scalar` είναι η *αφηρημένη* βάση - ορίζει `FETCH` και `STORE` που κράζουν, οπότε η απευθείας υποκλασοποίησή του σημαίνει ότι παρέχετε το δικό σας `TIESCALAR`. Καταφύγετε στο `Tie::StdScalar` όταν θέλετε έναν λειτουργικό κατασκευαστή δωρεάν· καταφύγετε στο `Tie::Scalar` μόνο όταν σκοπεύετε ούτως ή άλλως να γράψετε κάθε μέθοδο και θέλετε η διεπαφή να τεκμηριώνεται μέσω κληρονομικότητας. ## Δείτε επίσης - [`tie`](../../p5/core/perlfunc/tie.md) - η ενσωματωμένη, με το πλήρες μενού μεθόδων ανά τύπο - [`tied`](../../p5/core/perlfunc/tied.md) - ανακτήστε το αντικείμενο που στηρίζει τη μεταβλητή για να καλέσετε πάνω του μεθόδους ειδικές της κλάσης - [`untie`](../../p5/core/perlfunc/untie.md) - διαλύστε τη δέσμευση - [Hash με tie](hashes.md) - το επόμενο βήμα: ένας κατασκευαστής συν ένα πρωτόκολλο επανάληψης - `Tie::Scalar` - το άρθρωμα της βασικής κλάσης· το `Tie::StdScalar` είναι η συγκεκριμένη εκδοχή που συνήθως θέλετε