Menu
CoddyTech

יצירת גנריות

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