זרימת בקרה · מחלקות ותכנות מונחה־עצמים
method#
הצהרה על מתודת מופע בעלת שם בתוך בלוק class.
method מגדיר תת־שגרה שמצפה להיות מופעלת על עצם של המחלקה העוטפת. הוא מתנהג כמו sub, עם שתי הבטחות נוספות ש־sub אינו מעניק: ה־$self הלקסיקלי קשור ל־invocant באופן אוטומטי, וחתימות תמיד מופעלות - כותבים פרמטרים כאילו use feature 'signatures' היה בתוקף, ו־$self אינו מופיע בחתימה הזו.
method תקף רק בתוך הצהרת class. מחוץ לבלוק class זוהי שגיאת זמן־הידור.
הערה
תכונה ניסיונית מילות המפתח class, method ו־field הן חלק מתכונת ה־class הניסיונית (הוצגה ב־Perl 5.38). הפעלתה עם use feature 'class'; מנפיקה אזהרה בקטגוריה experimental::class. התחביר והסמנטיקה עדיין עשויים להשתנות בין מהדורות של Perl.
תקציר#
method NAME BLOCK
method NAME SIGNATURE BLOCK
method NAME : ATTRS BLOCK
method SIGNATURE BLOCK # anonymous
method BLOCK # anonymous
מה מקבלים בחזרה#
method בצורתו בעלת השם הוא הצהרה, לא ביטוי - הוא מתקין את המתודה בטבלת המתודות של המחלקה העוטפת ומוערך לכלום שימושי במיקום ההוראה. הצורה האנונימית מחזירה הפניית קוד שזוכרת את הקשר המחלקה וניתן לקרוא לה מאוחר יותר עם invocant של עצם.
לגוף של method קוראים עם העצם כ־invocant. ערך ההחזרה של המתודה הוא מה שהבלוק מחזיר, על־פי אותם כללי הקשר כמו קריאה לתת־שגרה רגילה.
מה ש־method נותן ש־sub אינו נותן#
ארבעה דברים שונים מכתיבת sub בתוך בלוק class:
$selfמוצהר מראש.$selfלקסיקלי נוצר בתחום המתודה ומאותחל ל־invocant. אין - ואין צורך - לבצע shift עליו מ־@_.חתימות תמיד מופעלות. אפשר לכתוב
method greet($name) { ... }ללאuse feature 'signatures'. ה־invocant$selfנצרך לפני שהחתימה נקשרת, ולכן הוא לעולם אינו מופיע ברשימת הפרמטרים.שדות בתחום. משתני
fieldשהוצהרו במחלקה העוטפת נראים בשמותיהם הלקסיקליים בתוך גוף המתודה.subפשוט בתוך בלוקclassאינו רואה שדות.הוא רשום כמתודה. טבלת המתודות של המחלקה רושמת את השם, וזה מה שמנגנון פתרון המתודות מחפש עבור dispatch של
$obj->name(...).subפשוט בתוך בלוק המחלקה הוא עוזר, לא מתודה.
במילים אחרות: sub בתוך בלוק class הוא תת־שגרת חבילה רגילה שבמקרה חיה במרחב השמות של אותה חבילה. אין לו $self, אין נראות שדות, והוא אינו חלק מממשק המתודות של המחלקה - יש לקרוא לו דרך ClassName::helper(...) אם מוכרחים, לא דרך חץ.
דוגמאות#
מחלקה מינימלית עם מתודה ושדה:
use v5.38;
use feature 'class';
no warnings 'experimental::class';
class Greeter {
field $greeting = "Hello";
method greet($name) {
return "$greeting, $name";
}
}
my $g = Greeter->new;
say $g->greet("world"); # Hello, world
ברירות מחדל של חתימה עובדות בדיוק כפי שהן עובדות עבור sub:
class Greeter {
field $greeting = "Hello";
method greet($name = "someone") {
return "$greeting, $name";
}
}
say Greeter->new->greet; # Hello, someone
מתודה ללא פרמטרים עדיין משתמשת בצורת החתימה - ה־() הריקים אינם נדרשים, אך מותרים והם הסגנון הנפוץ כאשר המתודה מקבלת ארגומנטים במקומות אחרים במחלקה:
class Counter {
field $n = 0;
method inc { $n++ }
method value () { return $n }
}
מתודה אנונימית - שימושית כמפעל או כ־callback שזקוק לגישה ל־$self ולשדות:
class AnonMethodFactory {
method make_printer {
return method { say "called on $self" };
}
}
מתודה לקסיקלית (פרטית) המוצהרת עם my method. יש להפעיל אותה דרך אופרטור ->&, אשר עוקף את חיפוש המתודה וקורא ללקסיקלי ישירות כאילו הייתה מתודה:
class LexicalMethod {
my method _check ($x, $y) {
return $x > 0 && $y > 0;
}
method process ($x, $y) {
return unless $self->&_check($x, $y);
# ...
}
}
sub רגיל בתוך מחלקה, בניגוד ל־method - ה־sub הוא עוזר, ה־method הוא הממשק הציבורי:
class Temperature {
field $celsius;
sub _c_to_f ($c) { $c * 9 / 5 + 32 } # helper, no $self, no fields
method fahrenheit {
return _c_to_f($celsius);
}
}
מקרי קצה#
מחוץ לבלוק
classזוהי שגיאת זמן־הידור.method foo { ... }ברמת העל, או בתוךpackageשאינוclass, אינו מתפענח. יש להשתמש שם ב־sub.$selfהוא קריאה־בלבד במובן שלא ניתן להצהיר על לקסיקלי אחר באותו שם בראש המתודה - הוא כבר בתחום. השמה ל־$self(לדוגמה$self = ...) מותרת אך נדרשת לעיתים נדירות ואינה משנה את ה־invocant של הקורא.@_אינו רשימת הארגומנטים שאתם מצפים לה. תחת החתימות ש־methodמפעיל,@_בתוך הגוף ריק לאחר שהחתימה נקשרת, בדיוק כמו בכל תת־שגרה שמשתמשת בחתימה. יש לקרוא פרמטרים מהחתימה, לא מ־@_.סדר פתרון המתודות נקבע על־ידי המחלקה העוטפת.
methodעצמו אינו לוקח אפשרות MRO; ירושה ו־dispatch עוקבים אחר מה שהצהרתclassהגדירה דרך:isaומאפיינים קשורים.methodאינו משתתף ב־prototypes. מתודות מופעלות דרך dispatch, לא דרך קריאות ישירות לטבלת הסמלים, ולכן prototypes (המאפיין:prototype(...)עלsub) חסר השפעה כאן. יש להשתמש בחתימה כדי להגביל את צורת הקריאה.מאפיינים. הצורה
method NAME : ATTRS BLOCKמקבלת מאפיינים באותה דרך כמוsub NAME : ATTRS BLOCK. סט המאפיינים השימושיים על מתודות עדיין מתייצב עם תכונת ה־class; יש להתייעץ ב־upstream לפני הסתמכות על מותאמים אישית.מלכודת מתודה־אנונימית בהחזרה־ממתודה.
return method { ... }מחזיר הפניית קוד.method { ... }כביטוי האחרון של מתודה ללאreturnהוא עדיין הפניית קוד, אך קוראים לעיתים קרובות מבינים אותו בטעות כבלוק - יש להעדיףreturnמפורש לבהירות.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
תכונת ה־class - ולכן method - מסומנת כניסיונית ב־upstream; pperl יורש סטטוס זה ואת קטגוריית האזהרה experimental::class.
ראו גם#
class- מצהיר על החבילה ש־methodחי בתוכה;methodמתפענח רק בתוך בלוקclassfield- משתנים לכל־מופע שנראים בשם בתוך כלmethodשל המחלקה העוטפתsub- הצהרה על תת־שגרה רגילה; להשתמש בה עבור עוזרים בתוך מחלקה שאינם זקוקים ל־$selfאו לגישה לשדות__CLASS__- שם המחלקה הנוכחית, שימושי בתוך מתודות הזקוקות ל־dispatch בחזרה לקוד ברמת המחלקהreturn- החזרה מפורשת מגוף מתודה; מומלץ כאשר הביטוי האחרון הוא בעצמו צורה אנונימית שלmethod { ... }my- הקדםmyל־methodכדי להצהיר על מתודה לקסיקלית (פרטית) המופעלת דרך->&