יצירת גנריות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 27 מתוך 57.
יוצרים גנריקה של S4 באמצעות setGeneric(). גוף הפונקציה שלה הוא standardGeneric("name"), המקבילה של S4 ל־UseMethod(). setGeneric() מחזירה את שם הגנריקה, שמודפס כשקוראים לה ברמה העליונה:
setGeneric("area", function(shape) standardGeneric("area"))פלט:
[1] "area"עטפו את הקריאה ב־invisible() כדי שהשורה הזאת לא תופיע בפלט. לאחר מכן, setMethod("area", "Circle", ...) מוסיפה את המתודה למחלקה אחת:
setClass("Circle", slots = c(r = "numeric"))
setClass("Square", slots = c(side = "numeric"))
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
setMethod("area", "Square", function(shape) shape@side^2)
cat(area(new("Circle", r = 1)), area(new("Square", side = 3)))פלט:
3.141593 9למתודה יש אותם ארגומנטים כמו לגנרית שלה. כאשר הגנרית כוללת ..., מתודה יכולה להוסיף אחריהם ארגומנטים משלה בעלי שמות:
setClass("Circle", slots = c(r = "numeric"))
invisible(setGeneric("describe", function(x, ...) standardGeneric("describe")))
setMethod("describe", "Circle", function(x, ..., digits = 2) {
paste("circle of area", round(pi * x@r^2, digits))
})
c1 <- new("Circle", r = 2)
print(describe(c1))
print(describe(c1, digits = 4))פלט:
[1] "circle of area 12.57"
[1] "circle of area 12.5664"הפונקציה setMethod() דורשת שהגנרית כבר תהיה קיימת, ולכן טוענים תחילה את הקובץ עם setGeneric(). קריאה עבור מחלקה ללא מתודה נעצרת עם שגיאה שמציינת את החתימה:
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setClass("Circle", slots = c(r = "numeric"))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
area(42)פלט:
Error: unable to find an inherited method for function ‘area’ for signature ‘shape = "numeric"’
Execution haltedאתגר
קלצורות הן מחלקות S4 בשלושה קבצים. ב־Shape.R צרו את הגנריות area(shape) ו־perimeter(shape) באמצעות setGeneric(), כשהן עטופות ב־invisible(). ב־Circle.R וב־Square.R המחלקות מוגדרות; הוסיפו לכל אחת מהן את המתודות area ו־perimeter באמצעות setMethod().
הקוד שסופק קורא שורות circle 2 או square 3 ומדפיס circle: area 12.57, perimeter 12.57.
כתבו את הקוד שלכם ב־Shape.R, Circle.R וב־Square.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
source("Shape.R")
source("Circle.R")
source("Square.R")
# קוד הקלט והפלט שסופק: יש להשאיר אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
s <- if (p[1] == "circle") new("Circle", r = as.numeric(p[2])) else new("Square", side = as.numeric(p[2]))
cat(sprintf("%s: area %.2f, perimeter %.2f", p[1], area(s), perimeter(s)), "\n", sep = "")
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות S3
עבודה עם קבציםרשימות עם מחלקהפונקציות בנאימתודות print ו-formatמאמתים ופונקציות עזרחזרה – טמפרטורותתרגלו בעצמכם: קומפיילר R אונליין