Κλάσεις και αντικειμενοστρέφεια

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 προωθείται αυτούσια:

Μορφή VARIABLE

Κατασκευαστής που καλείται

Αναφορά διεπαφής

$scalar

CLASSNAME->TIESCALAR(LIST)

Tie::Scalar

@array

CLASSNAME->TIEARRAY(LIST)

Tie::Array

%hash

CLASSNAME->TIEHASH(LIST)

Tie::Hash

*FH (glob)

CLASSNAME->TIEHANDLE(LIST)

Tie::Handle

Τα ορίσματα του κατασκευαστή είναι συμβατικά αυτά που θα περνούσατε σε κάτι όπως η 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