הרחבה באמצעות contains
חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 32 מתוך 57.
contains = "Animal" הופך מחלקת S4 חדשה לתת־מחלקה של Animal. לתת־המחלקה יש את כל ה־slots של מחלקת האב, בנוסף ל־slots משלה, ו־new() מקבלת את כולם:
setClass("Animal", slots = c(name = "character", age = "numeric"))
setClass("Dog", contains = "Animal", slots = c(breed = "character"))
rex <- new("Dog", name = "Rex", age = 3, breed = "collie")
print(slotNames("Dog"))
cat(rex@name, rex@breed)פלט:
[1] "breed" "name" "age"
Rex collieשיטות שנכתבו עבור מחלקת האב פועלות גם עבור מחלקת הבת. כשאין לגנריקה שיטה עבור Dog, S4 משתמשת בשיטה עבור Animal:
setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
invisible(setGeneric("intro", function(a) standardGeneric("intro")))
setMethod("intro", "Animal", function(a) paste("I am", a@name))
print(intro(new("Dog", name = "Rex")))פלט:
[1] "I am Rex"מחלקת צאצא מחליפה מתודה של מחלקת האב באמצעות הגדרת מתודה משלה עבור אותו גנרי. המחלקה הספציפית ביותר קובעת, ותתי־מחלקות אחרות ממשיכות להשתמש במתודה של מחלקת האב:
setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Cat", contains = "Animal")
invisible(setGeneric("sound", function(a) standardGeneric("sound")))
setMethod("sound", "Animal", function(a) "...")
setMethod("sound", "Dog", function(a) "woof")
cat(sound(new("Dog", name = "Rex")), sound(new("Cat", name = "Tom")))פלט:
woof ...הביטוי is(x, "Animal") מחזיר TRUE עבור כלב, ומשבצת שהוגדרה כ-"Animal" מקבלת Dog. קוד שנכתב עבור מחלקת האב עובד עם כל תת־מחלקה:
setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Owner", slots = c(pet = "Animal"))
rex <- new("Dog", name = "Rex")
o <- new("Owner", pet = rex)
cat(is(rex, "Animal"), is(o@pet, "Dog"))פלט:
TRUE TRUEאתגר
קלעובדים ומנהלים הם מחלקות S4 בשני קבצים. Employee.R מצהיר על Employee (משבצות name, salary) ועל הפונקציה הגנרית describe(), ונדרשת בו מתודה עבור Employee שמחזירה Bo earns 40000. ב־Manager.R יש להצהיר על Manager, שיורשת מ־Employee ומוסיפה את המשבצת reports (מספרית), ולדרוס את describe() כך שתחזיר Ada earns 60000 and manages 4.
הקוד שסופק קורא שורות employee Bo 40000 או manager Ada 60000 4 ומדפיס את describe(), האם האובייקט הוא עובד, ואת המשבצות שלו.
יש לכתוב את הקוד שלך בקבצים 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", name = p[2], salary = as.numeric(p[3]), reports = as.numeric(p[4]))
} else {
new("Employee", name = p[2], salary = as.numeric(p[3]))
}
cat(describe(x), "\n", sep = "")
cat("is an employee: ", is(x, "Employee"), ", slots: ", paste(slotNames(x), collapse = ", "), "\n", sep = "")
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות S3
עבודה עם קבציםרשימות עם מחלקהפונקציות בנאימתודות print ו-formatמאמתים ופונקציות עזרחזרה – טמפרטורות7ירושה ב-S4
הרחבה באמצעות containscallNextMethodמחלקות וירטואליותבדיקת טיפוסים באמצעות is()סיכום – שומר גן החיותתרגלו בעצמכם: קומפיילר R אונליין