Εμβέλεια · Αρθρώματα · Κλάσεις και αντικειμενοστρέφεια
package#
Δηλώνει τον χώρο ονομάτων κατά τη μεταγλώττιση για τις δηλώσεις που ακολουθούν.
Η package λέει στον μεταγλωττιστή ποιον πίνακα συμβόλων να χρησιμοποιήσει όταν επιλύει μη προσδιορισμένα ονόματα στον κώδικα που πρόκειται να αναλύσει. Δεν δημιουργεί πακέτο με οποιαδήποτε σημασία σε χρόνο εκτέλεσης - τα πακέτα έρχονται στην ύπαρξη την πρώτη φορά που αποθηκεύεται κάτι μέσα τους. Αυτό που πραγματικά κάνει μια εντολή package είναι να αναπροσανατολίσει τον μεταγλωττιστή: από εδώ και στο εξής, το $foo σημαίνει $NAMESPACE::foo, το &bar σημαίνει &NAMESPACE::bar, και ούτω καθεξής, μέχρι την επόμενη εντολή package ή το τέλος της περικλείουσας εμβέλειας.
Σύνοψη#
package NAME;
package NAME VERSION;
package NAME { ... }
package NAME VER { ... }
Τι επιστρέφεται#
Η package είναι οδηγία μεταγλώττισης, όχι έκφραση. Δεν έχει χρήσιμη τιμή χρόνου εκτέλεσης - αντιμετωπίστε την ως εντολή. Η επίδρασή της είναι στον αναλυτή: όλα τα μετέπειτα μη προσδιορισμένα αναγνωριστικά επιλύονται στον πίνακα συμβόλων του NAME μέχρι να τερματιστεί η εμβέλεια.
Η μορφή με VERSION έχει μία ορατή παρενέργεια: ορίζει το $NAME::VERSION σε ένα αντικείμενο version χτισμένο από το VERSION. Αυτό συμβαίνει ακριβώς μία φορά ανά εντολή package NAME VERSION, κατά τη μεταγλώττιση.
Καθολική κατάσταση που επηρεάζει#
Το τρέχον πακέτο μεταγλώττισης. Κάθε εντολή
packageτο αντικαθιστά για το υπόλοιπο της εμβέλειας. Το__PACKAGE__επιστρέφει την τρέχουσα τιμή σε οποιοδήποτε σημείο της πηγής.$NAME::VERSION- ορίζεται όταν παρέχεται το όρισμαVERSION. Ορίστε το μόνο μία φορά ανά πακέτο.Ο στόχος πίνακας συμβόλων (stash) δημιουργείται κατά την πρώτη χρήση. Το stash ενός πακέτου είναι το ίδιο ένα hash με όνομα
%NAME::(οπότε τουmainείναι το%main::), με κλειδιά τα μη προσδιορισμένα ονόματα συμβόλων που κρατά. Τίποτα δεν συμπληρώνεται από την ίδια την εντολήpackage· μεταγενέστερες δηλώσεις (sub,our, αναθέσεις στο$NAME::foo, κ.λπ.) το γεμίζουν.
Οι τέσσερις μορφές#
package NAMESPACE#
Αλλάζει το πακέτο μεταγλώττισης σε NAMESPACE από αυτό το σημείο μέχρι το τέλος της τρέχουσας εμβέλειας (περικλείον μπλοκ, αρχείο ή eval). Αυτή είναι η κλασική μορφή «ένα πακέτο ανά αρχείο»:
package My::Thing;
sub new { ... } # defines &My::Thing::new
our $count = 0; # defines $My::Thing::count
1;
package NAMESPACE VERSION#
Ίδια εμβέλεια με τη γυμνή μορφή, επιπλέον ορίζει το $NAMESPACE::VERSION σε ένα αντικείμενο version. Το VERSION πρέπει να είναι αυστηρό version literal: είτε ένας θετικός δεκαδικός (1.23, 0.001) είτε ένα v-string με τελείες που ξεκινά με v και έχει τουλάχιστον τρία τμήματα (v1.2.3). Η εκθετική σημειογραφία δεν επιτρέπεται.
package My::Thing 1.042;
package My::Thing v1.2.3;
Ορίστε το $VERSION μόνο μία φορά ανά πακέτο - μια δεύτερη εντολή package NAME VERSION στο ίδιο πακέτο αντικαθιστά την πρώτη, και οι καταναλωτές use Module VERSION βλέπουν μόνο την τελική τιμή.
package NAMESPACE BLOCK#
Περιορίζει λεξιλογικά την αλλαγή πακέτου στο BLOCK. Μέσα στα άγκιστρα το πακέτο μεταγλώττισης είναι το NAMESPACE· έξω από το άγκιστρο κλεισίματος το προηγούμενο πακέτο επαναφέρεται. Αυτή είναι η μόνη μορφή που επαναφέρεται αυτόματα.
package Outer;
our $x = 1; # $Outer::x
package Inner {
our $y = 2; # $Inner::y
}
our $z = 3; # $Outer::z again
package NAMESPACE VERSION BLOCK#
Η μορφή μπλοκ με version literal. Η εμβέλεια επαναφέρεται στο άγκιστρο κλεισίματος· το $NAMESPACE::VERSION παραμένει ορισμένο.
package My::Sub v0.9.1 {
sub ping { "pong" }
}
Τι περιορίζει και τι δεν περιορίζει σε εμβέλεια η package#
Η package επηρεάζει τις δυναμικές μεταβλητές (πακέτου) και την επίλυση μη προσδιορισμένων ονομάτων. Δεν επηρεάζει τα λεξιλογικά:
my,state- δημιουργούνται στο λεξιλογικό pad, αόρατα σε αναζήτηση πακέτου. Μια εντολήpackageδεν τους κάνει τίποτα.local- οριοθετεί δυναμικά μια μεταβλητή πακέτου, η οποία εξακολουθεί να ανήκει σε όποιο πακέτο κατονομάζει το πλήρως προσδιορισμένο όνομά της.our- δηλώνει λεξιλογικό ψευδώνυμο προς μια μεταβλητή πακέτου στο τρέχον πακέτο μεταγλώττισης. Αυτός είναι ο μηχανισμός που επιτρέπει στοour $countμέσα σεpackage My::Thingνα γίνει ψευδώνυμο του$My::Thing::count.
Η αλλαγή πακέτου μετά από δήλωση our δεν αναπροσανατολίζει το ψευδώνυμο: το ψευδώνυμο δεσμεύτηκε στο πακέτο που ίσχυε όταν μεταγλωττίστηκε η our.
package Foo;
our $x; # aliases $Foo::x
package Bar;
$x = 1; # still writes $Foo::x
Αλληλεπίδραση με την use v5.36 και νεότερες#
Η use v5.36 (και κάθε use v5.36 ή νεότερη) ενεργοποιεί έμμεσα τις strict και warnings. Μόλις τεθεί σε ισχύ η strict, οι μη προσδιορισμένες μεταβλητές πακέτου απαιτούν δήλωση our (ή πλήρη προσδιορισμό). Σε συνδυασμό με εντολή package, ο ιδιωματικός σύγχρονος σκελετός αρχείου είναι:
package My::Thing 1.00;
use v5.36; # strict, warnings, say, signatures, ...
our @EXPORT_OK = qw(thingify);
sub thingify { ... }
1;
Η μορφή package NAME VERSION και η use VERSION είναι ανεξάρτητες: η πρώτη ορίζει το $My::Thing::VERSION· η δεύτερη ενεργοποιεί χαρακτηριστικά γλώσσας για το τρέχον αρχείο.
Ειδικά αναγνωριστικά που σημαίνουν πάντοτε main::#
Ένα μικρό σύνολο αναγνωριστικών τοποθετείται αναγκαστικά στο πακέτο main:: ανεξάρτητα από το τρέχον package:
STDIN,STDOUT,STDERR,ARGV,ARGVOUT@ARGV,@INC,%ENV,%SIG,%INCΤο αναγνωριστικό ενός χαρακτήρα
_, σε όλα τα sigils του: το filehandle κάτω παύλας που χρησιμοποιείται από τηνstatκαι τους ελέγχους αρχείων-X, το βαθμωτό$_, και ο πίνακας@_.
Η εγγραφή στο $! μέσα σε package Foo εξακολουθεί να γράφει στο $main::!. Αυτό είναι σκόπιμο: αυτά τα ονόματα θα ήταν άχρηστα αν μετακινούνταν με το πακέτο.
Παραδείγματα#
Ένα ελάχιστο αρχείο αρθρώματος. Το όνομα του αρχείου πρέπει να ταιριάζει με το όνομα του πακέτου (η require μεταφράζει το :: στον διαχωριστή καταλόγου):
# lib/My/Greeter.pm
package My::Greeter 1.00;
use v5.36;
sub new { my ($cls, %a) = @_; bless { %a }, $cls }
sub greet { my $self = shift; "hello, $self->{name}\n" }
1;
Δύο πακέτα σε ένα αρχείο με τη μορφή μπλοκ. Η εμβέλεια επαναφέρεται αυτόματα, οπότε το 1; στο κάτω μέρος δεν ανήκει σε κανένα συγκεκριμένο πακέτο - αποτιμάται σε όποιο πακέτο ήταν ενεργό στην κορυφή του αρχείου (main για σενάριο, το ίδιο το πακέτο του αρχείου για άρθρωμα):
package My::Thing {
sub do_stuff { ... }
}
package My::Thing::Helper {
sub helper { ... }
}
Εναλλαγή μπρος-πίσω με τη μορφή εντολής - νόμιμο αλλά σπάνια αυτό που θέλετε:
package A;
sub one { 1 } # &A::one
package B;
sub two { 2 } # &B::two
package A;
sub three { 3 } # &A::three
Ορισμός έκδοσης και ανάγνωσή της πίσω. Σημειώστε ότι το $VERSION είναι αντικείμενο version, όχι απλή συμβολοσειρά· μετατρέψτε σε συμβολοσειρά ή συγκρίνετε με version:
package Foo 1.23;
say $Foo::VERSION; # 1.23
say ref $Foo::VERSION; # version
Η our μέσα σε ένα πακέτο σάς δίνει λεξιλογικά οριοθετημένο ψευδώνυμο προς μια μεταβλητή πακέτου - ο καθιερωμένος τρόπος να δηλώνετε καθολικές σε επίπεδο αρθρώματος υπό strict:
package Counter;
use v5.36;
our $count = 0; # aliases $Counter::count
sub bump { $count++ }
Οριακές περιπτώσεις#
Η
package NAMESPACE VERSIONδέχεται μόνο αυστηρά version literals. Η εκθετική σημειογραφία (1e3), οι μη αριθμητικές συμβολοσειρές και τα v-strings δύο τμημάτων (v1.2) αποτελούν σφάλματα μεταγλώττισης.Ο διπλός ορισμός του
$VERSIONστο ίδιο πακέτο (είτε με δύο εντολέςpackage NAME VERSIONείτε με ρητή εκχώρηση μετά απόpackage NAME VERSION) είναι νόμιμος αλλά μπερδεύει - ηuse Module VERSIONελέγχει την τελική τιμή, ενώ τα εργαλεία του CPAN διαβάζουν όποια βρουν πρώτη. Δηλώστε την έκδοση μία φορά.Η μορφή μπλοκ είναι ξεχωριστή λεξιλογική εμβέλεια. Οι μεταβλητές
myκαιstateπου δηλώνονται μέσα σεpackage NAME { ... }δεν είναι ορατές απ” έξω, όπως και σε οποιοδήποτε άλλο μπλοκ.Η
package NAMESPACEχωρίς ακολουθούσα εντολή ή μπλοκ επηρεάζει το υπόλοιπο του αρχείου. Μιαpackageστην κορυφή ενός σεναρίου μετακινεί μόνιμα το σενάριο εκτός τουmain, που σημαίνει ότι το$main::ARGV[0]εξακολουθεί να είναι η λίστα ορισμάτων σας αλλά οι νεοδηλωμένες καθολικές ανήκουν στο νέο πακέτο. Σχεδόν ποτέ ένα σενάριο δεν θέλει αυτό.Ένα αρχείο που περιέχει μόνο
package Foo;και κανέναν άλλο κώδικα εξακολουθεί να μεταγλωττίζεται καθαρά και να δημιουργεί το stashFoo::στην πρώτη αναφορά - αλλά τοrequireσε αυτό επιστρέφει την τιμή της τελευταίας εντολής, που είναι η ίδια η εντολήpackage(ψευδής). Βάλτε1;στο τέλος κάθε αρχείου αρθρώματος.Εμφωλευμένες μορφές μπλοκ επαναφέρουν το άμεσα περικλείον πακέτο, όχι το
main:package Outer; package Inner { package Innermost { # __PACKAGE__ is Innermost } # __PACKAGE__ is Inner again } # __PACKAGE__ is Outer again
Η
packageμέσα σεeval. Η αλλαγή πακέτου περιορίζεται στο σώμα τηςeval. Τα σύμβολα που δημιουργήθηκαν κατά τηνevalπαραμένουν στα stashes τους (τα stashes είναι καθολικά), αλλά το πακέτο μεταγλώττισης επανέρχεται όταν τελειώσει ηeval.Απόστροφος ως διαχωριστής πακέτου. Ο απόστροφος ήταν ο αρχικός διαχωριστής χώρου ονομάτων της Perl: το
$main'sailσήμαινε$main::sail, πολύ πριν υπάρξει το::. Επιβιώνει μόνο για την ανάγνωση κώδικα εποχής Perl 4 και είναι απενεργοποιημένος υπό τα σύγχρονα πακέτα χαρακτηριστικών, οπότε ένα τρέχον πρόγραμμα γραμμένο μεuse v5.36(ή οποιοδήποτε πρόσφατο πακέτο) δεν θα τον αναγνωρίσει. Μην τον γράφετε· η διπλή άνω-κάτω τελεία::είναι ο μόνος διαχωριστής που πρέπει να χρησιμοποιεί ο τρέχων κώδικας.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
use- φορτώνει ένα άρθρωμα κατά τη μεταγλώττιση και εισάγει σύμβολα από το πακέτο του· συνήθως συνοδεύεται από δήλωσηpackageστην κορυφή του φορτωμένου αρχείουrequire- φορτώνει άρθρωμα ή αρχείο σε χρόνο εκτέλεσης· η εντολήpackageτου φορτωμένου αρχείου καθορίζει ποιο stash γεμίζουν οι δηλώσεις τουbless- συσχετίζει μια αναφορά με ένα πακέτο ώστε οι κλήσεις μεθόδων να διανέμονται στις υπορουτίνες εκείνου του πακέτου· η συγκολλητική ύλη μεταξύpackageκαι αντικειμενοστρέφειαςmy- δηλώνει λεξιλογική μεταβλητή που ηpackageδεν επηρεάζει· το αντίστοιχο των καθολικών πακέτουour- δηλώνει λεξιλογικό ψευδώνυμο προς μεταβλητή πακέτου στο τρέχον πακέτο μεταγλώττισης· ο strict-safe τρόπος να χρησιμοποιείτε καθολικές σε επίπεδο αρθρώματοςlocal- οριοθετεί δυναμικά την τιμή μιας μεταβλητής πακέτου χωρίς να αλλάζει σε ποιο πακέτο ανήκει