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