וקטורי מחלקה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 12 מתוך 57.
הירושה ב-S3 נובעת מווקטור המחלקות. אובייקט עם class = c("manager", "employee") הוא מנהל וגם עובד. כשאין לגנרית מתודה עבור manager, ההפעלה ממשיכה ומפעילה את המתודה של employee:
pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
m <- structure(list(name = "Ada", salary = 60000), class = c("manager", "employee"))
print(class(m))
print(pay(m))פלט:
[1] "manager" "employee"
[1] 5000כתיבת וקטור המחלקות ידנית בכל בנאי חוזרת על הפרטים של מחלקת האב. במקום זאת, הבנאי של מחלקת האב מקבל ארגומנט class ומוסיף אותו לפני המחלקה שלו, והבנאי של מחלקת הבן קורא לבנאי של מחלקת האב:
new_employee <- function(name, salary, ..., class = character()) {
structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
new_manager <- function(name, salary, reports) {
new_employee(name, salary, reports = reports, class = "manager")
}
m <- new_manager("Ada", 60000, 4)
print(class(m))
print(names(m))פלט:
[1] "manager" "employee"
[1] "name" "salary" "reports"ה־... של בנאי מחלקת האב אוסף את השדות הנוספים של מחלקת הבת, כאן reports, ומציב אותם אחרי השדות של מחלקת האב. לעובד רגיל אין כלל שדה reports:
new_employee <- function(name, salary, ..., class = character()) {
structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
e <- new_employee("Bo", 40000)
print(class(e))
print(names(e))פלט:
[1] "employee"
[1] "name" "salary"הסדר של וקטור המחלקות חשוב: המחלקה הספציפית ביותר מופיעה ראשונה. כאשר מחלקת האב מופיעה ראשונה, המתודות שלה מנצחות והמתודות של מחלקת הבת לעולם אינן בשימוש:
title <- function(x) UseMethod("title")
title.employee <- function(x) "employee"
title.manager <- function(x) "manager"
right <- structure(list(), class = c("manager", "employee"))
wrong <- structure(list(), class = c("employee", "manager"))
print(title(right))
print(title(wrong))פלט:
[1] "manager"
[1] "employee"אתגר
קלהעובדים והמנהלים מחולקים בין שני קבצים. השלימו את new_employee(name, salary, ..., class = character()) בקובץ Employee.R: היא מחזירה רשימה עם name, salary וכל שדות נוספים מתוך ..., יחד עם וקטור המחלקות c(class, "employee"). לאחר מכן השלימו את new_manager(name, salary, reports) בקובץ Manager.R, שקוראת ל־new_employee() עם השדה הנוסף reports והמחלקה manager.
label() ומתודת employee שלה נתונות, כך שגם מנהלים מקבלים תווית בלי מתודה משלהם. הקוד שסופק קורא שורות כגון employee Bo 40000 או manager Ada 60000 4 ומדפיס את וקטור המחלקות, את שמות השדות ואת התווית.
הקוד שלכם ייכתב בקבצים Employee.R ו־Manager.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
source("Employee.R")
source("Manager.R")
# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
x <- if (p[1] == "manager") new_manager(p[2], as.numeric(p[3]), as.numeric(p[4])) else new_employee(p[2], as.numeric(p[3]))
cat("class: ", paste(class(x), collapse = ", "), "\n", sep = "")
cat("fields: ", paste(names(x), collapse = ", "), "\n", sep = "")
cat(label(x), "\n", sep = "")
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות S3
עבודה עם קבציםרשימות עם מחלקהפונקציות בנאימתודות print ו-formatמאמתים ופונקציות עזרחזרה – טמפרטורותתרגלו בעצמכם: קומפיילר R אונליין