Menu
Coddy logo textTech

יצירת גנריות

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

אתגר

קל

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

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

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

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