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

ref#

מחזיר מחרוזת המתארת על מה הפניה מצביעה.

ref בוחן את האופרנד שלו ומחזיר מחרוזת המזהה את סוג הישות המוצבעת. עבור הפניה ש־blessed עליה הוא מחזיר את שם המחלקה; עבור הפניה שאינה blessed הוא מחזיר אחת ממחרוזות הטיפוס הפנימיות (SCALAR, ARRAY, HASH, CODE, GLOB, LVALUE, IO, FORMAT, REF, VSTRING, REGEXP). עבור כל דבר שאינו הפניה הוא מחזיר את המחרוזת הריקה. ללא ארגומנט, ref פועל על $_.

תקציר#

ref EXPR
ref

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

מחרוזת. שלוש קטגוריות זרות זו לזו:

  • הפניה ש־blessed עליה - שם המחלקה שאל תוכה הישות המוצבעת blessed. לדוגמה, הפניה bless {}, 'Dog' מחזירה "Dog". תת־מחלקות מחזירות את שמן שלהן, לא של ההורה: הפניה ש־blessed עליה לתוך Puppy (ISA של Dog) מחזירה "Puppy". ראו bless.

  • הפניה שאינה blessed - אחת ממחרוזות הטיפוס הפנימיות המפורטות למטה, המזהה את הטיפוס הפיזי של הישות המוצבעת.

  • לא־הפניה - המחרוזת הריקה "".

המחרוזת הריקה היא ערך השקר היחיד ש־ref אי־פעם מחזיר, ולכן if (ref $x) היא בדיקת ״האם זוהי הפניה?״ בטוחה. ראו את סעיף מקרי הקצה להסבר מדוע if (ref $x eq 'HASH') אינה בדיקת ״האם זוהי הפניית האש?״ בטוחה.

מחרוזות טיפוס פנימיות#

מוחזרות עבור הפניות שאינן blessed בהתאם לישות הפיזית המוצבעת:

מחרוזת

ישות מוצבעת

SCALAR

הפניה לסקלר רגיל

ARRAY

הפניה למערך

HASH

הפניה להאש

CODE

הפניה לתת־שגרה

GLOB

הפניה ל־typeglob

LVALUE

הפניה לביטוי שניתן להשמה

IO

הפניה למטפל קלט/פלט

FORMAT

הפניה ל־format

REF

הפניה להפניה אחרת

VSTRING

הפניה לסקלר v-string

REGEXP

הפניה ל־regexp גולמי (לא־blessed)

regex מהודר מ־qr// הוא blessed לתוך המחלקה Regexp בזמן היצירה, אז ref qr/.../ מחזיר בדרך כלל "Regexp", לא "REGEXP". המחרוזת REGEXP העירומה מופיעה רק עבור ישויות regex לא־blessed, שהן נדירות מחוץ למימוש הפנימי.

דוגמאות#

בחינות טיפוס בסיסיות:

ref \1              # "SCALAR"
ref []              # "ARRAY"
ref {}              # "HASH"
ref sub { }         # "CODE"
ref \*STDOUT        # "GLOB"
ref \\1             # "REF"    (reference to a reference)
ref qr/foo/         # "Regexp" (blessed)
ref "plain string"  # ""       (not a reference)
ref 42              # ""
ref undef           # ""

הפניות ש־blessed עליהן מחזירות את שם המחלקה:

my $obj = bless {}, 'My::Widget';
ref $obj;                       # "My::Widget"

שמירה לפני dereferencing:

sub stringify {
    my ($v) = @_;
    return "[undef]"           if !defined $v;
    return "[ref: " . ref($v) . "]" if ref $v;
    return $v;
}

צורה ללא־ארגומנט קוראת את $_:

for my $item (@things) {
    print "skipping non-ref\n" and next unless ref;
    ...
}

בחירת הבדיקה הנכונה#

ref הוא הפרימיטיב הוותיק ביותר של בחינה־עצמית בשפה והוא מערבב שלוש שאלות שונות. קוד מודרני צריך לבחור את האופרטור התואם את השאלה הנשאלת.

האם זוהי הפניה בכלל?

if (ref $x) { ... }             # empty string is the only false return

האם זה עצם של (או נגזר מ־) מחלקה נתונה? השתמשו באופרטור isa (או המתודה UNIVERSAL::isa) - הוא סורק את @ISA ומכבד תת־מחלוּת, מה שהשוואת ref מילולית אינה עושה:

if ($obj isa 'My::Widget') { ... }      # true for subclasses too
if ($obj->isa('My::Widget')) { ... }    # method form

if (ref($obj) eq 'My::Widget') { ... }  # FRAGILE: fails for subclasses

מהו הטיפוס הפיזי הבסיסי, ללא תלות ב־blessing? השתמשו ב־Scalar::Util::reftype - הוא מתעלם מהמחלקה ומחזיר את מחרוזת הטיפוס הפנימית אפילו עבור הפניות ש־blessed עליהן:

use Scalar::Util qw(reftype blessed);
reftype($obj);                  # "HASH" if $obj is blessed hash ref
blessed($obj);                  # class name, or undef if not blessed

מקרי קצה#

  • לעולם אל תשתמשו ב־ref כערך אמת של הישות המוצבעת. הפניה ש־blessed עליה לתוך מחלקה ששמה מילולית 0 גורמת ל־ref $obj להחזיר את המחרוזת "0", שהיא שקרית. זה נדיר בעיצוב אבל ה־foot-gun הוא ישן וידוע. השוו למחרוזת הריקה במקום: if (ref $x ne "").

  • שמות מחלקה מתנגשים עם מחרוזות טיפוס פנימיות. דבר אינו מונע מכם לכתוב package HASH; sub new { bless {}, shift }. ואז ref(HASH->new) מחזיר "HASH" - בלתי ניתן להבחנה מהפניה לא־blessed להאש על־ידי ref לבדו. השתמשו ב־Scalar::Util::blessed כדי לפענח את העמימות, או ב־reftype כדי לשאול את שאלת הטיפוס־הפיזי ישירות.

  • ref על qr// מחזיר "Regexp", לא "REGEXP". עצמי qr// הם blessed בבנייה; הצורה הגדולה מופקת רק עבור ההפניה ה־(לא־רגילה) ל־regex לא־blessed.

  • משתנים שעברו tie: ref רואה דרך ה־tie אל ההפניה הבסיסית. השתמשו ב־tied כדי לאחזר את העצם שמגבה את ה־tie.

  • הפניות חלשות הן עדיין הפניות: ref מתנהג זהה עבור refs חלשות וחזקות. השתמשו ב־Scalar::Util::isweak לזיהוי חולשה.

  • Stringification ש־overloaded אינו משפיע על ref. ערך ההחזרה של ref מופק על־ידי ה־runtime, לא על־ידי ה־overload של "" של העצם.

  • ל־ref EXPR יש קדימות גבוהה מאוד - הוא מפוענח כאופרטור אונרי בעל שם. השתמשו בסוגריים כשהארגומנט הוא משהו מורכב יותר ממשתנה פשוט:

    ref $a || $b;         # parsed as (ref $a) || $b
    ref($a || $b);        # what you probably meant
    

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

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

  • isa - בדיקת חברות במחלקה המכבדת ירושת @ISA; העדיפו זאת על־פני ref(...) eq 'ClassName' ל־OO dispatch

  • tied - אחזור העצם המממש משתנה שעבר tie; ref על סקלר שעבר tie עוקב אחר ה־tie אל הישות המוצבעת

  • Scalar::Util::reftype - מחרוזת טיפוס־פיזי עבור הפניה, מתעלמת מ־blessing

  • Scalar::Util::blessed - שם המחלקה אם blessed, undef אחרת; המקבילה החד־משמעית ל־ref עבור קוד OO

  • perlref, perlobj - מדריכי עיון להפניות ולמודל העצמים