Menu
Coddy logo textTech

סמנטיקת העתקה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-R של Coddy. שיעור 39 מתוך 57.

אובייקטים מסוג S3 ו-S4 הם ערכים: פונקציה שמשנה אחד מהם משנה את העותק שלה. אובייקטים מסוג RC הם הפניות: האובייקט של הקורא משתנה. אותה פונקציה מתנהגת אחרת עבור שני הסוגים:

setClass("S4Box", slots = c(n = "numeric"))
RCBox <- setRefClass("RCBox", fields = list(n = "numeric"))
bump_s4 <- function(b) { b@n <- b@n + 1; invisible(b) }
bump_rc <- function(b) b$n <- b$n + 1
v <- new("S4Box", n = 1)
r <- RCBox$new(n = 1)
bump_s4(v)
bump_rc(r)
cat(v@n, r$n)

פלט:

1 2

$copy() יוצרת אובייקט חדש ועצמאי עם אותם ערכי שדות. שינוי העותק לא משנה את המקור:

Account <- setRefClass("Account", fields = list(balance = "numeric"))
a <- Account$new(balance = 100)
alias <- a
backup <- a$copy()
alias$balance <- 0
cat(a$balance, backup$balance)

פלט:

0 100

רשימה יכולה להכיל את אותו אובייקט RC כמה פעמים. שינוי של איבר אחד משנה את כולם. צרו אובייקט חדש לכל איבר כאשר הם צריכים להיות בלתי תלויים:

Counter <- setRefClass("Counter", fields = list(n = "numeric"))
one <- Counter$new(n = 0)
same <- list(one, one, one)
same[[1]]$n <- 5
fresh <- lapply(1:3, function(i) Counter$new(n = 0))
fresh[[1]]$n <- 5
cat(same[[3]]$n, fresh[[3]]$n)

פלט:

5 0

identical(a, b) מחזיר TRUE עבור שני שמות של אותו אובייקט RC, ו-FALSE עבור עותק, גם כאשר השדות עדיין שווים:

Account <- setRefClass("Account", fields = list(balance = "numeric"))
a <- Account$new(balance = 100)
b <- a
c2 <- a$copy()
cat(identical(a, b), identical(a, c2), c2$balance == a$balance)

פלט:

TRUE FALSE TRUE
challenge icon

אתגר

קל

עורך טקסט שומר נקודות שמירה. הכריזו על מחלקת הייחוס Document בתוך Document.R עם השדה text (character) ועם המתודה type(s), שמוסיפה את s לטקסט. לאחר מכן כתבו את checkpoint(doc), שמחזירה עותק עצמאי של המסמך.

ההגדרה עם המתודות עטופה ב־suppressMessages(). הקוד שסופק מתחיל בנקודת שמירה, ואז קורא פקודות: save שומרת את checkpoint(doc), הפקודה undo חוזרת לעותק של נקודת השמירה האחרונה, וכל שורה אחרת מוקלדת. אחרי כל פקודה הקוד מדפיס את הטקסט ואת הטקסט שנשמר, לכן נקודת שמירה לעולם לא צריכה להשתנות בזמן שממשיכים להקליד.

הקוד שלך צריך להופיע ב־Document.R. הקובץ main.R מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.

נסו בעצמכם

source("Document.R")

# קוד הקלט/פלט שסופק: השאירו אותו כפי שהוא
input <- suppressWarnings(readLines(file("stdin")))
doc <- Document$new(text = "")
saved <- checkpoint(doc)
for (cmd in input) {
  if (cmd == "save") {
    saved <- checkpoint(doc)
  } else if (cmd == "undo") {
    doc <- checkpoint(saved)
  } else {
    doc$type(cmd)
  }
  cat(cmd, " -> [", doc$text, "] saved [", saved$text, "]\n", sep = "")
}
quiz iconבחנו את עצמכם

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

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

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