זרימת בקרה

PACKAGE#

מחזיר את שם החבילה שבתוקף בנקודה שבה הטוקן מופיע.

__PACKAGE__ הוא ליטרל זמן־הידור: הפרסר מחליף אותו בקבוע מחרוזת שמכיל את שם החבילה שהוראת package האחרונה הכניסה לתוקף עבור התחום הלקסיקלי הזה. הוא לא מחפש דבר בזמן ריצה, לא עוקב אחרי ירושה, ולא איכפת לו באיזו מחלקה הקוד הקורא משתמש - הוא פשוט שם החבילה שבבעלותה נמצא קוד המקור שבו הוא יושב.

תקציר#

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

מה מקבלים בחזרה#

מחרוזת רגילה שמכילה את שם החבילה המוסמך במלואו (לדוגמה "My::Thing", "main"), מאוחסנת בזמן הידור. הערך הוא קבוע למשך התחום העוטף - הוא אינו יכול להשתנות בזמן ריצה ואינו תלוי באופן שבו הקוד נקרא.

מחוץ לכל הצהרת package מפורשת, הערך הוא "main".

מצב גלובלי שהוא נוגע בו#

אין. __PACKAGE__ נפתר בזמן הידור מהחבילה הלקסיקלית שבתוקף במיקום המקור שלו; הוא לא קורא מצב מפרש בעת ההרצה ואין לו תופעות לוואי.

מדוע להשתמש בטוקן במקום לכתוב את השם#

שלוש סיבות, לפי הסדר שבו נתקלים בהן בפועל:

  1. שם הקובץ מוחלף או שם החבילה מוחלף ושום דבר אחר אינו צריך להשתנות. כל __PACKAGE__ מתעדכן אוטומטית; כל "My::Thing" שהוקלד ביד יש לאתר ולערוך.

  2. זו הדרך הניידת היחידה לכתוב ״המחלקה הזו״ בתוך צורת בלוק package, שבה החבילה מסתיימת בסוגר הסוגר ועוזר פנימי אינו יכול להניח ששם הקובץ תואם.

  3. הוא מתחבר היטב עם מתודות מחלקה: __PACKAGE__->new(...) בעוזר בנאי קורא למחלקה הנכונה בין אם הקובץ נטען ישירות או הועתק לתת־מחלקה שעדיין לא הגדירה מחדש את העוזר.

עבור המקבילה בזמן ריצה - ״לאיזו מחלקה $self בעצם blessed?״ - יש להשתמש ב־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 הוא המחלקה שהעצם בעצם blessed לתוכה. מתודה הנירשת ממחלקת בסיס מחזירה את מחלקת הבסיס מ־__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 (ראש סקריפט, ראש one-liner), __PACKAGE__ הוא "main".

  • __PACKAGE__ אינו אומר ״המחלקה הנוכחית״. תחת use feature 'class', שם המחלקה ושם החבילה תואמים בשורת ההצהרה אך יכולים להיות שונים באתר קריאה שמופעל על תת־מחלקה. בתוך method, עדיף __CLASS__ כאשר רוצים את המחלקה של המקבל.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • package - ההצהרה שקובעת מה __PACKAGE__ מחזיר; כל ערך שאינו main מגיע מאחת כזו

  • __CLASS__ - המקבילה בזמן ריצה עבור קוד בתוך בלוק class: מחזיר את המחלקה של המופע המפעיל, שעשוי להיות תת־מחלקה

  • ref - שואלים עצם לאיזו מחלקה הוא blessed; הכלי הנכון כאשר יש $self ורוצים את המחלקה שלו בפועל

  • caller - החבילה הקוראת בזמן ריצה; יש להשתמש כאשר צריך את החבילה של הקורא, לא את שלכם

  • bless - הפרימיטיב שהופך הפניה לעצם של חבילה נתונה; בדרך כלל משולב עם בנאים בסגנון __PACKAGE__->new(...)

  • our - מצהיר על כינוי לקסיקלי למשתנה חבילה בחבילת זמן־ההידור הנוכחית (אותה חבילה ש־__PACKAGE__ נוקב בשמה)