Menu
Coddy logo textTech

יסודות NextMethod

חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 10 מתוך 57.

בתוך מתודה, NextMethod() קוראת למתודה הבאה בתור עבור אותו גנרי, עם אותם ארגומנטים. עבור אובייקט עם מחלקה אחת, המתודה הבאה היא ברירת המחדל, ולכן מתודה יכולה לעשות שימוש חוזר בתשובה הכללית ולהוסיף עליה:

describe <- function(x) UseMethod("describe")
describe.default <- function(x) paste("an object with", length(x), "fields")
describe.task <- function(x) paste0(NextMethod(), ", titled ", x$title)
t <- structure(list(title = "Buy milk", done = FALSE), class = "task")
print(describe(t))

פלט:

[1] "an object with 2 fields, titled Buy milk"

לאובייקט יכולות להיות כמה מחלקות בווקטור, כמו c("urgent", "task"). מנגנון השיגור מנסה אותן לפי הסדר, ו־NextMethod() בתוך השיטה הראשונה עובר לשיטה של המחלקה הבאה:

describe <- function(x) UseMethod("describe")
describe.task <- function(x) paste("task:", x$title)
describe.urgent <- function(x) paste("URGENT", NextMethod())
fix <- structure(list(title = "Fix the leak"), class = c("urgent", "task"))
print(describe(fix))

פלט:

[1] "URGENT task: Fix the leak"

NextMethod() מעבירה הלאה כל ארגומנט שהמתודה קיבלה, כולל ארגומנטים נוספים כמו sep. המתודה הבאה רואה את אותם ערכים בלי שתצטרכו לציין אותם שוב:

label <- function(x, sep = ": ") UseMethod("label")
label.default <- function(x, sep = ": ") paste0("item", sep, x$name)
label.box <- function(x, sep = ": ") paste0("[", NextMethod(), "]")
b <- structure(list(name = "tools"), class = "box")
print(label(b))
print(label(b, sep = " = "))

פלט:

[1] "[item: tools]"
[1] "[item = tools]"

Base R משתמשת ב-NextMethod() כדי לשמור על מחלקה כאשר יוצרים תת-קבוצה של וקטור. ברירת המחדל של [ מסירה את המחלקה, ולכן מתודה בשם "[.percent" מאפשרת לו לבצע את העבודה ולהחזיר את המחלקה:

format.percent <- function(x, ...) paste0(unclass(x) * 100, "%")
"[.percent" <- function(x, i) structure(NextMethod(), class = "percent")
p <- structure(c(0.1, 0.25, 0.5), class = "percent")
print(format(p[2:3]))

פלט:

[1] "25%" "50%"
challenge icon

אתגר

קל

משימות ומשימות דחופות הן שתי מחלקות בשני קבצים. ב־Task.R יש להשלים את describe() הגנרית, את שיטת ברירת המחדל, שמחזירה an item, ואת describe.task(), שמחזירה an item: Buy milk באמצעות קריאה ל־NextMethod() והוספת הכותרת. ב־Urgent.R יש להשלים את describe.urgent(), שמחזירה URGENT an item: Fix bug באמצעות קריאה ל־NextMethod().

הבנאים נתונים: למשימה דחופה יש את המחלקה c("urgent", "task"). הקוד שסופק קורא שורות כמו task Buy milk, urgent Fix bug או כל מילה אחרת עם כותרת, שהופכות לאובייקט של אותה מחלקה, ומדפיס את describe() עבור כל אחת מהן.

יש לכתוב את הקוד שלך ב־Task.R וב־Urgent.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.

נסו בעצמכם

source("Task.R")
source("Urgent.R")

# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  kind <- sub(" .*", "", line)
  title <- sub("^[a-z]+ ", "", line)
  t <- if (kind == "urgent") new_urgent(title) else if (kind == "task") new_task(title) else structure(list(title = title), class = kind)
  cat(describe(t), "\n", sep = "")
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר R אונליין