Menu
Coddy logo textTech

וקטורי מחלקה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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"
challenge icon

אתגר

קל

העובדים והמנהלים מחולקים בין שני קבצים. השלימו את 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 = "")
}
quiz iconבחנו את עצמכם

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

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

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