מחלקות ותכנות מונחה־עצמים

CLASS#

מחזיר את שם המחלקה של המופע שעליו פועלים כעת.

__CLASS__ הוא טוקן המזוהה בזמן הידור, ומחושב בזמן ריצה לשם המחלקה של המופע הקורא. בתוך גוף method או ביטוי מאתחל field (המופעל על־ידי use feature 'class'), הוא מספק את המחלקה בפועל של העצם הנמצא בבנייה או בשימוש - אשר עשויה להיות תת־מחלקה של החבילה שבה הקוד מצוי טקסטואלית. מחוץ לקוד של תכונת המחלקות הוא שקול בעיקרו ל־ref($self), אך בשונה מ־ref הוא שמיש במאתחל שדה, היכן ש־$self עדיין אינו קשור.

תקציר#

use feature 'class';

field $x = __CLASS__->DEFAULT_X;        # in a field initializer
method m { return __CLASS__; }          # in a method body

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

מחרוזת רגילה: שם המחלקה של המופע הקורא. הערך הוא מאותו סוג של מחרוזת ש־ref מחזיר עבור הפניה blessed. הוא אינו הפניה; ניתן לקרוא עליו מתודות כפי שהיינו קוראים על כל שם מחלקה.

my $name = __CLASS__;                   # e.g. "DifferentCustomField"
my $obj  = __CLASS__->new(...);         # class-method dispatch

מתי הוא שונה מ־__PACKAGE__#

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

use feature 'class';

class Base {
    field $f = __CLASS__->default_f;    # evaluated per instance
    sub default_f { 10 }
    method class_name { __CLASS__ }
    method pkg_name  { __PACKAGE__ }
}

class Derived :isa(Base) {
    sub default_f { 20 }
}

my $obj = Derived->new;
$obj->class_name;                       # "Derived"
$obj->pkg_name;                         # "Base"
# $f was initialised to 20, not 10, because __CLASS__ dispatched
# through the Derived package.

בהקשר ללא ירושה (ללא תת־מחלוק), __CLASS__ ו־__PACKAGE__ מניבים את אותה מחרוזת.

דוגמאות#

מתודת מחלקה הנקראת ממאתחל שדה - המקרה הקנוני. בלי __CLASS__, תת־מחלקה אינה יכולה לעקוף את ברירת המחדל:

use feature 'class';

class WithCustomField {
    use constant DEFAULT_X => 10;
    field $x = __CLASS__->DEFAULT_X;
}

class DifferentCustomField :isa(WithCustomField) {
    sub DEFAULT_X { rand > 0.5 ? 20 : 30 }
}

my $obj = DifferentCustomField->new;    # $x is 20 or 30, not 10

בתוך גוף מתודה, שקול ל־ref $self:

class Logger {
    method log ($msg) {
        print STDERR "[", __CLASS__, "] $msg\n";
    }
}

בניית מופע חדש מאותה מחלקה כמו העצם הקורא - שימושי למתודות factory דמויות־clone שחייבות לכבד תת־מחלקות:

class Node {
    field $label :param;
    method spawn ($child_label) {
        return __CLASS__->new(label => $child_label);
    }
}

השוואה עם __PACKAGE__ עבור אבחונים הרוצים לציין במדויק את יעד הדיספאץ«:

class Thing {
    method describe {
        return sprintf "defined in %s, dispatched as %s",
            __PACKAGE__, __CLASS__;
    }
}

מקרי קצה#

  • תקף רק תחת use feature 'class' בתוך גוף method, מאתחל field, או מבנה אחר של תכונת המחלקות (לדוגמה בלוקי ADJUST). שימוש בו מחוץ להקשר כזה הוא שגיאת זמן הידור.

  • ללא סוגריים, ללא ארגומנטים. __CLASS__ הוא טוקן bareword, לא קריאת פונקציה. __CLASS__() היא שגיאת תחביר.

  • אינו זהה ל־ref $self במהלך אתחול שדות - $self עדיין אינו קשור בעת ששדות נקבעים, ולכן ref $self אינו זמין. __CLASS__ הוא הדרך היחידה להגיע אל מחלקת המופע מתוך מאתחל שדה.

  • לא ref עבור קריאת מתודת מחלקה. כאשר נקרא כמתודת מחלקה (ללא מופע ביד), __CLASS__ מניב את המחלקה שעליה נקראה המתודה, לא את החבילה שבה הוגדרה המתודה. זה משקף דיספאץ« מתודה רגיל.

  • מחרוזת, לא הפניה. קריאות מתודה דרך __CLASS__->... הן דיספאצ’ים של מתודת־מחלקה, לא דיספאצ’ים של מתודת־מופע. המתודה לא תראה הפניה blessed כ־invocant שלה.

  • התכונה class מסומנת כניסיונית ב־Perl 5.42; היא פולטת אזהרת experimental::class אלא אם הושתקה באמצעות no warnings 'experimental::class'.

הבדלים מ־upstream#

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

ראו גם#

  • __PACKAGE__ - שם החבילה של הקוד המקיף בזמן הידור; השתמשו בזה כשרוצים את החבילה הטקסטואלית, לא את מחלקת זמן הריצה

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

  • bless - משייך הפניה עם שם מחלקה; הפרימיטיב ברמה הנמוכה שאליו נפתרת בסופו של דבר הדיספאץ« בסגנון __CLASS__

  • isa - בודק האם המחלקה הנוכחית היא תת־מחלקה של שם נתון; משתלב באופן טבעי עם __CLASS__ לבדיקות בזמן ריצה

  • sub - מצהיר על תת־שגרות, כולל הצורה method שהופכת את __CLASS__ למשמעותי