Ροή ελέγχου

PACKAGE#

Επιστρέφει το όνομα του πακέτου που είναι σε ισχύ στο σημείο όπου εμφανίζεται το token.

Η __PACKAGE__ είναι κυριολεκτικό κατά τη μεταγλώττιση: ο αναλυτής την αντικαθιστά με μια σταθερή συμβολοσειρά που κατονομάζει όποιο πακέτο έθεσε σε ισχύ η πιο πρόσφατη δήλωση package για αυτή τη λεξιλογική εμβέλεια. Δεν αναζητεί τίποτα κατά τον χρόνο εκτέλεσης, δεν ακολουθεί την κληρονομικότητα και δεν την αφορά ποια κλάση χρησιμοποιεί ο καλών κώδικας - είναι απλώς το όνομα του πακέτου στο οποίο ανήκει το πηγαίο κείμενο που την περιέχει.

Σύνοψη#

__PACKAGE__
__PACKAGE__->some_method(@args)
$__PACKAGE__::VERSION          # does NOT work - see Edge cases

Τι επιστρέφεται#

Μια απλή συμβολοσειρά που περιέχει το πλήρως κατονομασμένο όνομα πακέτου (π.χ. "My::Thing", "main"), εσωτερικευμένη κατά τη μεταγλώττιση. Η τιμή είναι σταθερά για όλη τη διάρκεια της περικλείουσας εμβέλειας - δεν μπορεί να αλλάξει κατά τον χρόνο εκτέλεσης και δεν εξαρτάται από τον τρόπο κλήσης του κώδικα.

Εκτός οποιασδήποτε ρητής δήλωσης package, η τιμή είναι "main".

Καθολική κατάσταση που επηρεάζει#

Καμία. Η __PACKAGE__ επιλύεται κατά τη μεταγλώττιση από το λεξιλογικό πακέτο που είναι σε ισχύ στην πηγαία της θέση· δεν διαβάζει καμία κατάσταση του διερμηνέα όταν εκτελείται και δεν έχει παρενέργειες.

Γιατί να χρησιμοποιήσετε ένα token αντί να γράψετε το όνομα#

Τρεις λόγοι, με τη σειρά που τους συναντάτε στην πράξη:

  1. Το αρχείο ή το πακέτο μετονομάζεται και τίποτε άλλο δεν χρειάζεται να αλλάξει. Κάθε __PACKAGE__ ενημερώνεται αυτόματα· κάθε χειρωνακτικά γραμμένο "My::Thing" πρέπει να εντοπιστεί και να διορθωθεί.

  2. Είναι ο μόνος φορητός τρόπος για να γράψετε «αυτή την κλάση» μέσα σε μορφή μπλοκ package, όπου το πακέτο τελειώνει στην κλείνουσα αγκύλη και ένας εσωτερικός βοηθός δεν μπορεί να υποθέσει ότι το όνομα αρχείου ταιριάζει.

  3. Συνδυάζεται καθαρά με μεθόδους κλάσης: το __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__)