Κλάσεις και αντικειμενοστρέφεια
tie#
Δέσιμο μιας μεταβλητής σε μια κλάση ώστε κάθε πρόσβαση στη μεταβλητή να δρομολογείται μέσω των μεθόδων αυτής της κλάσης.
Η tie μαγεύει τη VARIABLE ώστε επόμενες αναγνώσεις, εγγραφές και άλλες λειτουργίες σε αυτήν να προωθούνται στις μεθόδους της tie-διεπαφής του CLASSNAME (FETCH, STORE, FIRSTKEY, PRINT, …). Η LIST περνά στον κατασκευαστή της κλάσης (TIESCALAR, TIEARRAY, TIEHASH ή TIEHANDLE, ανάλογα με το sigil της VARIABLE). Ο κατασκευαστής επιστρέφει το υποκείμενο δεσμευμένο αντικείμενο, και αυτό το αντικείμενο - όχι η VARIABLE - είναι η τιμή επιστροφής της tie. Κρατήστε το αν θέλετε να καλέσετε επιπλέον μεθόδους στην υλοποίηση άμεσα.
Το συμβόλαιο μεθόδων που πρέπει να ικανοποιεί κάθε κλάση τεκμηριώνεται εκτενώς στο perltie· αυτή η σελίδα τεκμηριώνει την tie ως built-in.
Σύνοψη#
tie my $scalar, 'ScalarClass', @args;
tie my @array, 'ArrayClass', @args;
tie my %hash, 'HashClass', @args;
tie *FH, 'HandleClass', @args;
my $obj = tie my %h, 'HashClass', @args; # keep the tied object
Τι επιστρέφεται#
Το αντικείμενο που επιστρέφει ο κατασκευαστής TIE* της κλάσης - μια συνηθισμένη blessed αναφορά, ίδια με οποιοδήποτε άλλο αντικείμενο. Καλέστε μεθόδους πάνω του άμεσα όταν η κλάση εκθέτει λειτουργίες που δεν αντιστοιχούν σε απλή πρόσβαση μεταβλητής:
my $db = tie my %cache, 'My::Cache', path => '/var/cache/app.db';
$db->flush; # method on the tied object
$cache{key} = 'value'; # goes through STORE
Η tie δεν επιστρέφει την ίδια τη μεταβλητή. Κώδικας που γράφει my $x = tie ... και έπειτα αντιμετωπίζει το $x ως το βαθμωτό είναι κοινό λάθος αρχαρίων· το βαθμωτό είναι $x μόνο αν δεσμεύσατε επίσης το $x, και ο στόχος εκχώρησης είναι το δεσμευμένο αντικείμενο, όχι η μεταβλητή.
Για να ανακτήσετε το δεσμευμένο αντικείμενο από μια μεταβλητή αργότερα, χρησιμοποιήστε την tied. Για να διαλύσετε τη σύνδεση, χρησιμοποιήστε την untie.
Ποιος κατασκευαστής καλείται#
Το sigil της VARIABLE επιλέγει τον κατασκευαστή. Η LIST προωθείται αυτούσια:
Μορφή | Κατασκευαστής που καλείται | Αναφορά διεπαφής |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Τα ορίσματα του κατασκευαστή είναι συμβατικά αυτά που θα περνούσατε σε κάτι όπως η dbm_open(3) - ένα όνομα αρχείου, ένα mode, μια μάσκα δικαιωμάτων - αλλά οτιδήποτε αναμένει η κλάση είναι αποδεκτό.
Μέθοδοι που πρέπει να παρέχει κάθε κλάση#
Η ίδια η tie καλεί μόνο τις TIE*. Κάθε άλλη λειτουργία στη μεταβλητή δρομολογείται σε μέθοδο που ονοματίζεται κατά τη λειτουργία. Δεν είναι όλες οι μέθοδοι υποχρεωτικές - μέθοδοι που λείπουν κάνουν τις αντίστοιχες λειτουργίες να αποτυγχάνουν με σφάλμα κατά τον χρόνο εκτέλεσης. Τα πλήρη μενού είναι:
Δεσμευμένο βαθμωτό (TIESCALAR):
TIESCALAR classname, LIST
FETCH this
STORE this, value
DESTROY this
UNTIE this
Δεσμευμένος πίνακας (TIEARRAY):
TIEARRAY classname, LIST
FETCH this, index
STORE this, index, value
FETCHSIZE this
STORESIZE this, count
CLEAR this
PUSH this, LIST
POP this
SHIFT this
UNSHIFT this, LIST
SPLICE this, offset, length, LIST
EXTEND this, count
DELETE this, index
EXISTS this, index
DESTROY this
UNTIE this
Δεσμευμένος πίνακας κατακερματισμού (TIEHASH):
TIEHASH classname, LIST
FETCH this, key
STORE this, key, value
DELETE this, key
CLEAR this
EXISTS this, key
FIRSTKEY this
NEXTKEY this, lastkey
SCALAR this
DESTROY this
UNTIE this
Δεσμευμένο filehandle (TIEHANDLE):
TIEHANDLE this, LIST
READ this, scalar, length, offset
READLINE this
GETC this
WRITE this, scalar, length, offset
PRINT this, LIST
PRINTF this, format, LIST
BINMODE this
EOF this
FILENO this
SEEK this, position, whence
TELL this
OPEN this, mode, LIST
CLOSE this
DESTROY this
UNTIE this
Δείτε το perltie για την πλήρη προδιαγραφή (υπογραφές μεθόδων, πότε καλείται καθεμία, προεπιλογές που κληρονομούνται από τις βασικές κλάσεις Tie::*).
Παραδείγματα#
Δέσιμο ενός πίνακα κατακερματισμού σε αρχείο DBM στον δίσκο και επανάληψη με each. Οι keys και values θα υλοποιούσαν όλο το σύνολο μονομιάς - για μεγάλα αρχεία DBM αυτό είναι ακριβό:
use NDBM_File;
tie(my %HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0);
while (my ($key, $val) = each %HIST) {
print $key, ' = ', unpack('L', $val), "\n";
}
Κρατήστε την τιμή επιστροφής του κατασκευαστή ώστε να μπορείτε να μιλάτε άμεσα στο δεσμευμένο αντικείμενο:
my $impl = tie my %cache, 'My::Cache', ttl => 60;
$cache{session} = $data; # STORE
$impl->expire_now; # direct method call
Δέσιμο βαθμωτού σε κλάση μόνο για ανάγνωση που καταγράφει κάθε πρόσβαση:
package Tie::Logged {
sub TIESCALAR { my ($class, $v) = @_; bless \$v, $class }
sub FETCH { my $self = shift; warn "read\n"; $$self }
sub STORE { my ($s, $v) = @_; warn "write\n"; $$s = $v }
}
tie my $x, 'Tie::Logged', 42;
print $x; # warns "read", prints 42
$x = 99; # warns "write"
Δέσιμο filehandle σε κλάση που συλλαμβάνει την έξοδο σε συμβολοσειρά:
package Tie::StringHandle {
sub TIEHANDLE { my $c = shift; bless { buf => '' }, $c }
sub PRINT { my $s = shift; $s->{buf} .= join '', @_; 1 }
sub buf { $_[0]->{buf} }
}
tie *OUT, 'Tie::StringHandle';
print OUT "hello\n";
print OUT "world\n";
my $obj = tied *OUT;
print $obj->buf; # "hello\nworld\n"
Οριακές περιπτώσεις#
Η τιμή επιστροφής είναι το αντικείμενο, όχι η μεταβλητή. Το
my $r = tie my %h, ...δένει το$rστο δεσμευμένο αντικείμενο. Η εκχώρηση στο$rεκχωρεί σε βαθμωτό· δεν γράφει διαμέσου του στο%h.Το άρθρωμα πρέπει να φορτωθεί πρώτα. Σε αντίθεση με την
dbmopen, ηtieδεν κάνειuseήrequireτοCLASSNAMEγια εσάς. Φορτώστε το ρητά:use My::TiedClass; tie my %h, 'My::TiedClass';
Η παράλειψη αυτού είναι η τυπική αιτία του
Can't locate object method "TIEHASH" via package ....Οι μέθοδοι που λείπουν είναι μοιραίες στο σημείο χρήσης, όχι στη στιγμή του
tie. Ένας δεσμευμένος πίνακας κατακερματισμού του οποίου η κλάση ορίζειFETCHαλλά όχιSTOREδένεται επιτυχώς, και έπειτα εγείρειCan't locate object method "STORE" ...στην πρώτη εκχώρηση.Η αναντιστοιχία sigil είναι σφάλμα στη στιγμή του
tie. Ηtieεπιλέγει τον κατασκευαστή από το sigil της μεταβλητής, οπότε μια κλάση που ορίζει μόνοTIESCALARδεν μπορεί να δεθεί σε πίνακα κατακερματισμού - η αναζήτηση τουTIEHASHαποτυγχάνει στην ίδια την κλήσηtie.Το
tieσε μια δεσμευμένη μεταβλητή σιωπηρά κάνει πρώταuntieτην προηγούμενη σύνδεση, πυροδοτώνταςUNTIEκαι τελικάDESTROYστο παλιό αντικείμενο (μόλις πέσει η τελευταία αναφορά σε αυτό).Η
localσε δεσμευμένη μεταβλητή αποθηκεύει και αποκαθιστά τη σύνδεση, όχι μόνο την τιμή. Κατά την έξοδο από την εμβέλεια η μεταβλητή ξαναδένεται στο αρχικό της αντικείμενο.Η διατήρηση επιπλέον αναφοράς στο δεσμευμένο αντικείμενο το κρατά ζωντανό πέρα από την
untie. Υπόuse warningsαυτό παράγει προειδοποίησηuntie attempted while N inner references still exist. Απορρίψτε την αναφορά (π.χ.undef $obj) πριν καλέσετε τηνuntieαν θέλετε ηDESTROYνα πυροδοτηθεί άμεσα.Η
tieδεν αποθηκεύει το αντικείμενο μέσα στη μεταβλητή με κανέναν ορατό στον χρήστη τρόπο - χρησιμοποιήστε τηνtiedγια να το ανακτήσετε· δεν υπάρχει σύνταξη αποαναφοράς που να το εκθέτει.Απόδοση. Κάθε λειτουργία σε δεσμευμένη μεταβλητή δρομολογείται μέσω κλήσης μεθόδου. Σε στενούς βρόχους αυτό είναι ορατά πιο αργό από απλή μεταβλητή· για μαζικές εργασίες, διαβάστε πρώτα σε απλό πίνακα ή πίνακα κατακερματισμού, λειτουργήστε, και έπειτα γράψτε πίσω.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
tied- ανάκτηση του αντικειμένου στο οποίο είναι δεσμευμένη μια μεταβλητή αυτή τη στιγμή, ήundefαν δεν είναι δεσμευμένηuntie- διάλυση της σύνδεσης και επιτρέπει την καταστροφή του δεσμευμένου αντικειμένουbless- η χαμηλού επιπέδου πρωτογενής που χρησιμοποιούν οι κατασκευαστέςTIE*για να μετατρέψουν μια αναφορά σε αντικείμενοdbmopen- παλαιότερη συντόμευση για τη συγκεκριμένη περίπτωση δεσίματος πίνακα κατακερματισμού σε αρχείο DBM· φορτώνει την κλάση DBM για εσάς, κάτι που ηtieδεν κάνειref- επιθεώρηση της κλάσης του αντικειμένου που επιστρέφει ηtie