callNextMethod
חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 33 מתוך 57.
בתוך מתודה של S4, callNextMethod() קוראת למתודה של מחלקת האב עם אותם הארגומנטים ומחזירה את התוצאה שלה. מתודת צאצא מתבססת על התשובה של מחלקת האב במקום לחזור עליה:
setClass("Employee", slots = c(name = "character", salary = "numeric"))
setClass("Manager", contains = "Employee", slots = c(reports = "numeric"))
invisible(setGeneric("describe", function(x) standardGeneric("describe")))
setMethod("describe", "Employee", function(x) paste(x@name, "earns", x@salary))
setMethod("describe", "Manager", function(x) paste(callNextMethod(), "and manages", x@reports))
print(describe(new("Manager", name = "Ada", salary = 60000, reports = 4)))פלט:
[1] "Ada earns 60000 and manages 4"זה עובד גם עבור show(): הילד מדפיס את השורות של ההורה ואז את השורות שלו:
setClass("Employee", slots = c(name = "character"))
setClass("Manager", contains = "Employee", slots = c(reports = "numeric"))
setMethod("show", "Employee", function(object) cat("Employee:", object@name, "\n"))
setMethod("show", "Manager", function(object) {
callNextMethod()
cat("Reports:", object@reports, "\n")
})
new("Manager", name = "Ada", reports = 4)פלט:
Employee: Ada
Reports: 4 new() קוראת ל־initialize() הגנרית. מתודה עבורה יכולה למלא חריצים שהערכים שלהם מחושבים מתוך אחרים. היא קוראת קודם ל־callNextMethod(.Object, ...), ולכן ההגדרה הרגילה ובדיקת התקינות עדיין מתבצעות:
setClass("Order", slots = c(prices = "numeric", total = "numeric"))
setMethod("initialize", "Order", function(.Object, ...) {
.Object <- callNextMethod(.Object, ...)
.Object@total <- sum(.Object@prices)
.Object
})
o <- new("Order", prices = c(2.5, 4, 1))
print(o@total)פלט:
[1] 7.5בדומה ל־NextMethod() ב־S3, callNextMethod() מתקדם בשרשרת דרך כמה רמות, כשכל מחלקה מוסיפה את החלק שלה:
setClass("Ticket", slots = c(base = "numeric"))
setClass("Vip", contains = "Ticket")
setClass("Backstage", contains = "Vip")
invisible(setGeneric("price", function(t) standardGeneric("price")))
setMethod("price", "Ticket", function(t) t@base)
setMethod("price", "Vip", function(t) callNextMethod() * 2)
setMethod("price", "Backstage", function(t) callNextMethod() + 50)
cat(price(new("Ticket", base = 30)), price(new("Vip", base = 30)), price(new("Backstage", base = 30)))פלט:
30 60 110אתגר
קלהכרטיסים מגיעים בשלוש רמות, כל אחת בקובץ משלה. המחלקות והגנרית price() מוגדרות. הוסיפו את המתודות:
Ticket.R: price()הוא המחיר הבסיסי; show()מדפיסהTicket for galaושורה חדשה.Vip.R: price()הוא פי 1.5 ממחיר הכרטיס; show()מדפיסה את שורת הכרטיס ואז אתVIP lounge access.Backstage.R: price()הוא מחיר ה־VIP בתוספת 50; show()מדפיסה את שורות ה־VIP ואז אתBackstage pass.
השתמשו ב־callNextMethod() במתודות של מחלקות המשנה. הקוד שסופק קורא שורות vip gala 80 (רמה, אירוע, מחיר בסיסי) ומדפיס כל כרטיס ואת מחירו.
הקוד שלכם ייכנס לקבצים Ticket.R, Vip.R ו־Backstage.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
source("Ticket.R")
source("Vip.R")
source("Backstage.R")
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
base <- as.numeric(p[3])
t <- switch(p[1],
standard = new("Ticket", event = p[2], base = base),
vip = new("VipTicket", event = p[2], base = base),
backstage = new("BackstageTicket", event = p[2], base = base))
print(t)
cat(sprintf("price: %.2f", price(t)), "\n", sep = "")
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות S3
עבודה עם קבציםרשימות עם מחלקהפונקציות בנאימתודות print ו-formatמאמתים ופונקציות עזרחזרה – טמפרטורות7ירושה ב-S4
הרחבה באמצעות containscallNextMethodמחלקות וירטואליותבדיקת טיפוסים באמצעות is()סיכום – שומר גן החיותתרגלו בעצמכם: קומפיילר R אונליין