tie#
לקשור משתנה למחלקה כך שכל גישה למשתנה תופנה דרך המתודות של אותה מחלקה.
tie מקסים את VARIABLE כך שקריאות, כתיבות, ופעולות אחרות עליו מועברות למתודות ממשק ה־tie של CLASSNAME (FETCH, STORE, FIRSTKEY, PRINT, …). LIST מועבר לקונסטרקטור של המחלקה (TIESCALAR, TIEARRAY, TIEHASH, או TIEHANDLE, תלוי ב־sigil של VARIABLE). הקונסטרקטור מחזיר את העצם הקשור הבסיסי, ועצם זה - לא VARIABLE - הוא ערך ההחזרה של tie. יש לשמור אותו אם רוצים לקרוא למתודות נוספות על המימוש ישירות.
חוזה המתודות שכל מחלקה חייבת לקיים מתועד באריכות ב־perltie; עמוד זה מתעד את tie המובנה.
תקציר#
tie my $scalar, 'ScalarClass', @args;
tie my @array, 'ArrayClass', @args;
tie my %hash, 'HashClass', @args;
tie *FH, 'HandleClass', @args;
my $obj = tie my %h, 'HashClass', @args; # keep the tied object
מה מקבלים בחזרה#
העצם שהקונסטרקטור TIE* של המחלקה מחזיר - הפניה מבורכת רגילה, כמו כל עצם אחר. יש לקרוא למתודות עליו ישירות כאשר המחלקה חושפת פעולות שאינן ממופות לגישת משתנה פשוטה:
my $db = tie my %cache, 'My::Cache', path => '/var/cache/app.db';
$db->flush; # method on the tied object
$cache{key} = 'value'; # goes through STORE
tie אינו מחזיר את המשתנה עצמו. קוד שכותב my $x = tie ... ואז מתייחס ל־$x כסקלר הוא טעות מתחילים נפוצה; הסקלר הוא $x רק אם גם קשרת את $x, ויעד ההשמה הוא העצם הקשור, לא המשתנה.
לשחזור העצם הקשור ממשתנה מאוחר יותר, יש להשתמש ב־tied. לפירוק הקישור, יש להשתמש ב־untie.
איזה קונסטרקטור נקרא#
ה־sigil של VARIABLE בוחר את הקונסטרקטור. LIST מועבר verbatim:
צורת | קונסטרקטור שנקרא | הפניית ממשק |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
הארגומנטים של הקונסטרקטור הם לפי המוסכמה אלה שהיית מעביר למשהו כמו dbm_open(3) - שם קובץ, מצב, מסכת הרשאה - אך כל דבר שהמחלקה מצפה לו תקין.
מתודות שכל מחלקה חייבת לספק#
tie עצמו רק מפעיל את TIE*. כל פעולה אחרת על המשתנה מופנית למתודה ששמה על שם אותה פעולה. לא כל המתודות חובה - מתודות חסרות גורמות לפעולות המתאימות להיכשל עם שגיאת זמן ריצה. התפריטים המלאים הם:
סקלר קשור (TIESCALAR):
TIESCALAR classname, LIST
FETCH this
STORE this, value
DESTROY this
UNTIE this
מערך קשור (TIEARRAY):
TIEARRAY classname, LIST
FETCH this, index
STORE this, index, value
FETCHSIZE this
STORESIZE this, count
CLEAR this
PUSH this, LIST
POP this
SHIFT this
UNSHIFT this, LIST
SPLICE this, offset, length, LIST
EXTEND this, count
DELETE this, index
EXISTS this, index
DESTROY this
UNTIE this
האש קשור (TIEHASH):
TIEHASH classname, LIST
FETCH this, key
STORE this, key, value
DELETE this, key
CLEAR this
EXISTS this, key
FIRSTKEY this
NEXTKEY this, lastkey
SCALAR this
DESTROY this
UNTIE this
מטפל קובץ קשור (TIEHANDLE):
TIEHANDLE this, LIST
READ this, scalar, length, offset
READLINE this
GETC this
WRITE this, scalar, length, offset
PRINT this, LIST
PRINTF this, format, LIST
BINMODE this
EOF this
FILENO this
SEEK this, position, whence
TELL this
OPEN this, mode, LIST
CLOSE this
DESTROY this
UNTIE this
ראו perltie למפרט המלא (חתימות מתודות, מתי כל אחת נקראת, ברירות מחדל שמורשות ממחלקות הבסיס Tie::*).
דוגמאות#
לקשור האש לקובץ DBM על הדיסק ולעבור עליו עם each. keys ו־values היו מממשים את כל הקבוצה בבת אחת - עבור קבצי DBM גדולים זה יקר:
use NDBM_File;
tie(my %HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0);
while (my ($key, $val) = each %HIST) {
print $key, ' = ', unpack('L', $val), "\n";
}
לשמור את ערך ההחזרה של הקונסטרקטור כדי שתוכל לדבר עם העצם הקשור ישירות:
my $impl = tie my %cache, 'My::Cache', ttl => 60;
$cache{session} = $data; # STORE
$impl->expire_now; # direct method call
לקשור סקלר למחלקה לקריאה־בלבד שרושמת ביומן כל גישה:
package Tie::Logged {
sub TIESCALAR { my ($class, $v) = @_; bless \$v, $class }
sub FETCH { my $self = shift; warn "read\n"; $$self }
sub STORE { my ($s, $v) = @_; warn "write\n"; $$s = $v }
}
tie my $x, 'Tie::Logged', 42;
print $x; # warns "read", prints 42
$x = 99; # warns "write"
לקשור מטפל קובץ למחלקה שלוכדת פלט לתוך מחרוזת:
package Tie::StringHandle {
sub TIEHANDLE { my $c = shift; bless { buf => '' }, $c }
sub PRINT { my $s = shift; $s->{buf} .= join '', @_; 1 }
sub buf { $_[0]->{buf} }
}
tie *OUT, 'Tie::StringHandle';
print OUT "hello\n";
print OUT "world\n";
my $obj = tied *OUT;
print $obj->buf; # "hello\nworld\n"
מקרי קצה#
ערך ההחזרה הוא העצם, לא המשתנה.
my $r = tie my %h, ...קושר את$rלעצם הקשור. השמה ל־$rמשימה לסקלר; היא אינה כותבת דרכו ל־%h.המודול חייב להיטען קודם. שלא כמו
dbmopen,tieאינו מבצעuseאוrequireל־CLASSNAMEעבורך. יש לטעון אותו במפורש:use My::TiedClass; tie my %h, 'My::TiedClass';
שכחת זה היא הסיבה הטיפוסית של
Can't locate object method "TIEHASH" via package ....מתודות חסרות הן קטלניות בנקודת השימוש, לא בזמן ה־
tie. האש קשור שהמחלקה שלו מגדירהFETCHאבל לאSTOREנקשר בהצלחה, ואז מעלהCan't locate object method "STORE" ...בהשמה הראשונה.אי־התאמת sigil היא שגיאת זמן
tie.tieבוחר את הקונסטרקטור מה־sigil של המשתנה, כך שמחלקה שמגדירה רקTIESCALARאינה יכולה להיקשר ב־tieלהאש - החיפוש שלTIEHASHנכשל בקריאת ה־tieעצמה.tieעל משתנה קשור מבצעuntieמשתמע לקישור הקודם קודם, מפעילUNTIEובסופו של דברDESTROYעל העצם הישן (ברגע שההפניה האחרונה אליו נשמטת).localעל משתנה קשור שומר ומשחזר את הקישור, לא רק את הערך. ביציאת התחום המשתנה נקשר מחדש לעצם המקורי שלו.החזקת הפניה נוספת לעצם הקשור משאירה אותו בחיים מעבר ל־
untie. תחתuse warningsזה מייצר אזהרתuntie attempted while N inner references still exist. יש להשליך את ההפניה (לדוגמהundef $obj) לפני קריאה ל־untieאם רוצים ש־DESTROYיופעל מיד.tieאינו מאחסן את העצם בתוך המשתנה בשום דרך גלויה למשתמש - יש להשתמש ב־tiedכדי לאחזר אותו; אין תחביר dereference שחושף אותו.ביצועים. כל פעולה על משתנה קשור מופנית דרך קריאת מתודה. בלולאות הדוקות זה איטי יותר באופן נראה לעין ממשתנה פשוט; לעבודה בכמויות, יש לקרוא למערך או האש פשוטים קודם, לבצע, ואז לכתוב חזרה.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
tied- לשחזר את העצם שמשתנה קשור אליו כעת, אוundefאם אינו קשורuntie- לפרק את הקישור ולתת לעצם הקשור להיהרסbless- הפרימיטיב ברמה נמוכה שקונסטרקטוריTIE*משתמשים בו כדי להפוך הפניה לעצםdbmopen- קיצור ישן יותר למקרה הספציפי של קשירת האש לקובץ DBM; טוען את מחלקת ה־DBM עבורך, מה ש־tieאינו עושהref- לבחון את המחלקה של העצם המוחזר על־ידיtie