סקלרים קשורים#
סקלר קשור הוא ממשק ה־tie הקטן ביותר והמקום הטוב ביותר ללמוד את הצורה של כל האחרים. אתם מגדירים בנאי ושתי מתודות accessor; מאותו רגע, כל קריאה של המשתנה קוראת לאחת מהן וכל כתיבה קוראת לאחרת.
המחלקה זקוקה לארבע מתודות, שתיים מהן אופציונליות:
TIESCALAR- הבנאי, נקרא פעם אחת על ידיtie.FETCH- נקראת בכל קריאה של המשתנה.STORE- נקראת בכל כתיבה אל המשתנה.DESTROY- נקראת כאשר המשתנה הקשור נעלם (אופציונלי).
רשימת החתימות המלאה נמצאת בעמוד העזר tie. פרק זה מראה מה כל מתודה עושה באמצעות בניית אחת כזו.
מחלקה שלמה#
מונה שמגביל כתיבות כך שהערך לעולם אינו יורד מתחת לאפס:
use v5.36;
package Counter {
sub TIESCALAR {
my ($class, $start) = @_;
my $n = $start // 0;
return bless \$n, $class;
}
sub FETCH { my $self = shift; return $$self }
sub STORE {
my ($self, $value) = @_;
$$self = $value < 0 ? 0 : $value; # never go below zero
}
sub DESTROY { }
}
tie my $hits, 'Counter', 10;
say $hits; # 10
$hits = 25;
say $hits; # 25
$hits = -7;
say $hits; # 0
העצם שמאחורי הסקלר יכול להיות כל דבר שעבר blessed - כאן הפניה למספר רגיל. ה־LIST שאחרי שם המחלקה בקריאת tie (10) מועבר ישירות אל TIESCALAR.
חוזה המתודות#
TIESCALAR classname, LISTהבנאי. הוא מקבל את שם המחלקה ואת כל הארגומנטים הנוספים שהועברו אל
tie. הוא חייב להחזיר הפניה שעברה blessed; אותה הפניה הופכת לעצם הקשור ולערך ההחזרה של קריאתtie. קיצור דרך נפוץ הוא הפניית סקלר שעברה blessed ומחזיקה את הערך, כמו למעלה, אבל הפניית האש שעברה blessed תקפה בדיוק באותה מידה כאשר המחלקה זקוקה ליותר מצב.FETCH thisנקראת בכל פעם שהמשתנה נקרא. היא מקבלת רק את העצם. כל מה שהיא מחזירה הוא מה שהקורא רואה.
FETCHהוא המקום שבו סקלר מחושב מצדיק את עצמו: הוא יכול לחשב מחדש, לחפש משהו, או לרשום את הגישה ולהחזיר ערך מאוחסן.STORE this, valueנקראת בכל פעם שמתבצעת השמה למשתנה. היא מקבלת את העצם ואת הערך החדש היחיד. ערך ההחזרה שלה נזנח - ערך ביטוי ההשמה מגיע מ־
FETCHעוקב, לא מ־STORE. כאן שוכנים האימות, ההגבלה, או הכתיבה־מבעד אל מאגר תומך.DESTROY thisנקראת כאשר המשתנה הקשור מושמד (יציאה מתחום, או נפילת ההפניה האחרונה). הגדירו אותה רק כאשר המחלקה מחזיקה משאב שדורש שחרור - מטפל פתוח, נעילה. למונה אין דבר לנקות, ולכן ה־
DESTROYשלו ריק או מושמט לחלוטין.
תזמון הקריאה#
קריאה בכל הקשר קוראת ל־
FETCH.say $hits,$x = $hits + 1, ו־"$hits"כל אחד מהם מפעילFETCHאחד.השמה קוראת ל־
STOREעם הערך שמימין.$hits = 25קורא ל־STORE($obj, 25).השמה מורכבת קוראת ואז כותבת:
$hits += 5קורא ל־FETCH, מוסיף 5, ואזSTORE. כך גם$hits++.הערך של ביטוי השמה מגיע מ־
FETCH, לא מערך ההחזרה שלSTORE. לאחרmy $r = ($hits = -7),$rהוא0מכיוון שההגבלה רצה ב־STOREוערך הביטוי נשלף בחזרה.
מחלקה מינימלית ברת־קיימא#
הסקלר הקשור השמיש הקטן ביותר מגדיר בדיוק את TIESCALAR, FETCH, ו־STORE. השמיטו את DESTROY אלא אם אתם מקצים משהו. מחלקה עם TIESCALAR ו־FETCH בלבד מייצרת סקלר לקריאה בלבד: היא נקשרת כראוי, אבל ההשמה הראשונה מתה עם Can't locate object method "STORE".
הדרך הקלה: ירושה מ־Tie::StdScalar#
Tie::StdScalar (מסופק בתוך Tie::Scalar) מממש את TIESCALAR, FETCH, STORE, ו־DESTROY מעל הפניית סקלר שעברה blessed. ירשו ממנו ועקפו רק את הוו שאתם רוצים לשנות:
package Uppercase {
use Tie::Scalar;
our @ISA = ('Tie::StdScalar');
sub STORE { my ($self, $v) = @_; $$self = uc $v }
}
tie my $shout, 'Uppercase';
$shout = 'hello';
say $shout; # HELLO
STORE ממיר לאותיות רישיות בדרך פנימה; FETCH והבנאי מגיעים ממחלקת הבסיס ללא שינוי.
Tie::Scalar עצמו הוא הבסיס המופשט - הוא מגדיר FETCH ו־STORE שעושים croak, ולכן יצירת תת־מחלקה ממנו ישירות פירושה אספקת TIESCALAR משלכם. פנו אל Tie::StdScalar כאשר אתם רוצים בנאי פועל בחינם; פנו אל Tie::Scalar רק כאשר אתם מתכוונים לכתוב כל מתודה בכל מקרה ורוצים שהממשק יתועד באמצעות ירושה.
ראו גם#
tie- המובנה, עם תפריט המתודות המלא לכל סוגtied- שחזרו את העצם שתומך במשתנה כדי לקרוא עליו מתודות ספציפיות למחלקהuntie- פירוק הקישורהאשים קשורים - השלב הבא למעלה: בנאי בתוספת פרוטוקול איטרציה
Tie::Scalar- מודול מחלקת הבסיס;Tie::StdScalarהוא הגרסה הקונקרטית שבדרך כלל תרצו