Βαθμωτά με tie#
Ένα βαθμωτό με tie είναι η μικρότερη διεπαφή tie και το καλύτερο μέρος για να μάθετε τη μορφή όλων των υπολοίπων. Ορίζετε έναν κατασκευαστή και δύο μεθόδους προσπέλασης· από εκεί και πέρα, κάθε ανάγνωση της μεταβλητής καλεί τη μία και κάθε εγγραφή καλεί την άλλη.
Η κλάση χρειάζεται τέσσερις μεθόδους, οι δύο από τις οποίες είναι προαιρετικές:
TIESCALAR- ο κατασκευαστής, που καλείται μία φορά από τοtie.FETCH- καλείται σε κάθε ανάγνωση της μεταβλητής.STORE- καλείται σε κάθε εγγραφή στη μεταβλητή.DESTROY- καλείται όταν η μεταβλητή με tie παύει να υπάρχει (προαιρετική).
Η πλήρης λίστα υπογραφών βρίσκεται στη σελίδα αναφοράς του tie. Αυτό το κεφάλαιο δείχνει τι κάνει κάθε μέθοδος φτιάχνοντας μία.
Μια πλήρης κλάση#
Ένας μετρητής που περικόπτει τις εγγραφές ώστε η τιμή να μην πέφτει ποτέ κάτω από το μηδέν:
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 που θέλετε να αλλάξετε:
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- η ενσωματωμένη, με το πλήρες μενού μεθόδων ανά τύποtied- ανακτήστε το αντικείμενο που στηρίζει τη μεταβλητή για να καλέσετε πάνω του μεθόδους ειδικές της κλάσηςuntie- διαλύστε τη δέσμευσηHash με tie - το επόμενο βήμα: ένας κατασκευαστής συν ένα πρωτόκολλο επανάληψης
Tie::Scalar- το άρθρωμα της βασικής κλάσης· τοTie::StdScalarείναι η συγκεκριμένη εκδοχή που συνήθως θέλετε