PACKAGE#
Επιστρέφει το όνομα του πακέτου που είναι σε ισχύ στο σημείο όπου εμφανίζεται το token.
Η __PACKAGE__ είναι κυριολεκτικό κατά τη μεταγλώττιση: ο αναλυτής την αντικαθιστά με μια σταθερή συμβολοσειρά που κατονομάζει όποιο πακέτο έθεσε σε ισχύ η πιο πρόσφατη δήλωση package για αυτή τη λεξιλογική εμβέλεια. Δεν αναζητεί τίποτα κατά τον χρόνο εκτέλεσης, δεν ακολουθεί την κληρονομικότητα και δεν την αφορά ποια κλάση χρησιμοποιεί ο καλών κώδικας - είναι απλώς το όνομα του πακέτου στο οποίο ανήκει το πηγαίο κείμενο που την περιέχει.
Σύνοψη#
__PACKAGE__
__PACKAGE__->some_method(@args)
$__PACKAGE__::VERSION # does NOT work - see Edge cases
Τι επιστρέφεται#
Μια απλή συμβολοσειρά που περιέχει το πλήρως κατονομασμένο όνομα πακέτου (π.χ. "My::Thing", "main"), εσωτερικευμένη κατά τη μεταγλώττιση. Η τιμή είναι σταθερά για όλη τη διάρκεια της περικλείουσας εμβέλειας - δεν μπορεί να αλλάξει κατά τον χρόνο εκτέλεσης και δεν εξαρτάται από τον τρόπο κλήσης του κώδικα.
Εκτός οποιασδήποτε ρητής δήλωσης package, η τιμή είναι "main".
Καθολική κατάσταση που επηρεάζει#
Καμία. Η __PACKAGE__ επιλύεται κατά τη μεταγλώττιση από το λεξιλογικό πακέτο που είναι σε ισχύ στην πηγαία της θέση· δεν διαβάζει καμία κατάσταση του διερμηνέα όταν εκτελείται και δεν έχει παρενέργειες.
Γιατί να χρησιμοποιήσετε ένα token αντί να γράψετε το όνομα#
Τρεις λόγοι, με τη σειρά που τους συναντάτε στην πράξη:
Το αρχείο ή το πακέτο μετονομάζεται και τίποτε άλλο δεν χρειάζεται να αλλάξει. Κάθε
__PACKAGE__ενημερώνεται αυτόματα· κάθε χειρωνακτικά γραμμένο"My::Thing"πρέπει να εντοπιστεί και να διορθωθεί.Είναι ο μόνος φορητός τρόπος για να γράψετε «αυτή την κλάση» μέσα σε μορφή μπλοκ
package, όπου το πακέτο τελειώνει στην κλείνουσα αγκύλη και ένας εσωτερικός βοηθός δεν μπορεί να υποθέσει ότι το όνομα αρχείου ταιριάζει.Συνδυάζεται καθαρά με μεθόδους κλάσης: το
__PACKAGE__->new(...)σε έναν βοηθό κατασκευαστή καλεί τη σωστή κλάση είτε το αρχείο φορτώνεται απευθείας είτε αντιγράφεται σε μια υποκλάση που δεν έχει ακόμα επανορίσει τον βοηθό.
Για το αντίστοιχο κατά τον χρόνο εκτέλεσης - «σε ποια κλάση είναι πραγματικά blessed το $self;» - χρησιμοποιήστε το ref ή, σε κώδικα με use feature 'class', το __CLASS__. Δεν είναι το ίδιο πράγμα· δείτε Οριακές περιπτώσεις.
Παραδείγματα#
Ανάγνωση του τρέχοντος πακέτου μέσα σε ένα άρθρωμα:
package My::Thing;
say __PACKAGE__; # My::Thing
Χρησιμοποιήστε το __PACKAGE__ για να προσπελάσετε μια μεταβλητή πακέτου χωρίς να κωδικοποιήσετε σταθερά το όνομα - ανθεκτικό σε μετονομασίες:
package My::Thing;
our $VERSION = '1.23';
sub version_string {
no strict 'refs';
return ${ __PACKAGE__ . '::VERSION' };
}
Βοηθός κατασκευαστή που παραμένει σωστός όταν αντιγραφεί σε υποκλάση ή όταν το πακέτο εναλλάσσεται με τη μορφή μπλοκ:
package My::Widget {
sub new {
my ($class, %args) = @_;
bless { %args, kind => __PACKAGE__ }, $class;
}
}
# kind is always "My::Widget", even if someone calls
# My::Widget::SubClass->new and forgets to override `new`.
Ίχνος εκσφαλμάτωσης που τυπώνει από πού προήλθε μια γραμμή καταγραφής, χωρίς να χρειάζεται να επαναλάβετε το όνομα του πακέτου σε κάθε μήνυμα:
package My::Worker;
use v5.36;
sub log_debug {
my ($msg) = @_;
warn __PACKAGE__ . ": $msg\n";
}
Επίλυση μεταξύ πακέτων με τη μορφή μπλοκ - κάθε __PACKAGE__ βλέπει όποιο package την περιβάλλει:
package Outer;
say __PACKAGE__; # Outer
package Inner {
say __PACKAGE__; # Inner
}
say __PACKAGE__; # Outer again
Οριακές περιπτώσεις#
Σταθερά κατά τη μεταγλώττιση, όχι μεταβλητή. Η
__PACKAGE__δεν είναι βαθμωτό· οι$__PACKAGE__και${__PACKAGE__}δεν υπάρχουν. Παρεμβάλλεται σε συμβολοσειρές με διπλά εισαγωγικά ως η συμβολοσειρά στην οποία επιλύεται:package Foo; say "in @{[__PACKAGE__]}"; # in Foo say "in $__PACKAGE__"; # prints "in " - $__PACKAGE__ is undef
Το ιδίωμα
@{[ ... ]}είναι ο συντομότερος τρόπος για να την παρεμβάλετε.Η συμβολική αναφορά σε μεταβλητή πακέτου απαιτεί συνένωση συμβολοσειρών, όχι παρεμβολή sigil:
no strict 'refs'; my $v = ${ __PACKAGE__ . '::VERSION' }; # works my $v = ${"__PACKAGE__::VERSION"}; # WRONG - literal package
Δεν είναι το ίδιο με το
ref $self. Η__PACKAGE__είναι το σημείο όπου γράφτηκε ο πηγαίος κώδικας· τοref $selfείναι αυτό στο οποίο πραγματικά έγινε bless το αντικείμενο. Μια μέθοδος που κληρονομείται από μια βασική κλάση επιστρέφει τη βασική κλάση από την__PACKAGE__, αλλά την υποκλάση από τοref $self:package Base; sub who { (__PACKAGE__, ref $_[0]) } package Child; our @ISA = ('Base'); say join " / ", Child->who; # Base / Child
Όταν θέλετε την κλάση στην οποία επικλήθηκε η μέθοδος, χρησιμοποιήστε το
refστον επικαλούμενο (invocant), το__CLASS__μέσα σε ένα μπλοκclass/method, ή πάρτε το$_[0]/shiftως το όνομα της κλάσης για μια μέθοδο κλάσης.Εμβέλεια μορφής μπλοκ. Μέσα σε
package NAME { ... }, η__PACKAGE__είναιNAME· μετά την κλείνουσα αγκύλη η προηγούμενη τιμή αποκαθίσταται. Δείτε το εμφωλευμένο παράδειγμα παραπάνω.Το
eval STRINGσυλλαμβάνει το πακέτο μεταγλώττισής του. Η συμβολοσειρά μεταγλωττίζεται στο πακέτο του καλούντος, οπότε η__PACKAGE__μέσα σεeval "..."είναι το πακέτο που κάλεσε τοeval:package Foo; eval 'say __PACKAGE__'; # Foo
Πριν από οποιαδήποτε δήλωση
package(αρχή σεναρίου, αρχή μονόγραμμου), η__PACKAGE__είναι"main".Η
__PACKAGE__δεν σημαίνει «τρέχουσα κλάση». Υπόuse feature 'class', το όνομα κλάσης και το όνομα πακέτου συμφωνούν στη γραμμή δήλωσης, αλλά μπορούν να διαφέρουν σε ένα σημείο κλήσης που γίνεται σε υποκλάση. Μέσα σεmethod, προτιμήστε το__CLASS__όταν θέλετε την κλάση του παραλήπτη.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
package- η δήλωση που ορίζει τι επιστρέφει η__PACKAGE__· κάθε τιμή που δεν είναιmainπροέρχεται από μία τέτοια__CLASS__- το αντίστοιχο κατά τον χρόνο εκτέλεσης για κώδικα μέσα σε μπλοκclass: επιστρέφει την κλάση του επικαλούμενου στιγμιότυπου, που μπορεί να είναι υποκλάσηref- ρωτήστε ένα αντικείμενο σε ποια κλάση έγινε bless· το σωστό εργαλείο όταν έχετε το$selfκαι θέλετε την πραγματική του κλάσηcaller- το πακέτο που καλεί κατά τον χρόνο εκτέλεσης· χρησιμοποιήστε το όταν χρειάζεστε το πακέτο του καλούντος, όχι το δικό σαςbless- η πρωτογενής λειτουργία που μετατρέπει μια αναφορά σε αντικείμενο ενός δεδομένου πακέτου· τυπικά συνοδεύεται από κατασκευαστές τύπου__PACKAGE__->new(...)our- δηλώνει ένα λεξιλογικό ψευδώνυμο προς μια μεταβλητή πακέτου στο τρέχον πακέτο μεταγλώττισης (το ίδιο πακέτο που κατονομάζει η__PACKAGE__)