Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

دلالات النسخ

جزء من قسم البرمجة كائنية التوجه في رحلة 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 عبر الإنترنت