וקטורי מחלקה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-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 אונליין