البيئات ككائنات
جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 18 من 57.
البيئة هي مجموعة من القيم المسماة، مثل القائمة، يتم إنشاؤها باستخدام new.env(). والفرق هو أن البيئة لا يتم نسخها أبدًا: كل متغير يشير إليها يرى الكائن نفسه، لذلك يكون التغيير من خلال اسم واحد مرئيًا من خلال جميع الأسماء:
e <- new.env()
e$count <- 1
alias <- e
alias$count <- 99
print(e$count)
l <- list(count = 1)
copy <- l
copy$count <- 99
print(l$count)الناتج:
[1] 99
[1] 1الدالة التي تستقبل بيئةً تغيّر كائن المستدعي. ولا يتعين عليها إرجاع أي شيء، كما أن المستدعي لا يعيّن نتيجة:
deposit <- function(acc, x) acc$balance <- acc$balance + x
acc <- new.env()
acc$balance <- 10
deposit(acc, 5)
deposit(acc, 5)
print(acc$balance)المخرجات:
[1] 20assign() وget() وexists() تعمل مع اسم مخزّن في متغير، بينما تسرد ls() الأسماء في بيئة بترتيب فرز:
e <- new.env()
for (fruit in c("pear", "apple")) assign(fruit, nchar(fruit), envir = e)
print(ls(e))
print(get("pear", envir = e))
print(exists("kiwi", envir = e))الناتج:
[1] "apple" "pear"
[1] 4
[1] FALSEالبيئة التي تحتوي على سمة فئة هي كائن S3 يتمتع بدلالات المرجع: تعمل أساليبه كالمعتاد، وتُجري الدوال التي تغيّره التغييرَ في مكانه:
new_wallet <- function(coins = 0) {
w <- new.env()
w$coins <- coins
class(w) <- "wallet"
w
}
print.wallet <- function(x, ...) {
cat("wallet with", x$coins, "coins\n")
invisible(x)
}
spend <- function(w, n) w$coins <- w$coins - n
w <- new_wallet(10)
spend(w, 3)
wالناتج:
wallet with 7 coinsالتحدي
سهلالمخزون هو بيئة من الفئة inventory تحتوي على متغير واحد، وهو items، متجه رقمي مُسمّى يمثل المخزون. أكمل الملف Inventory.R:
- تنشئ
new_inventory()البيئة معitemsفارغ (يُعدc()مناسبًا) ومع الفئة. - تضيف
add_stock(inv, item, n)القيمةnإلى مخزون العنصر، بدءًا من 0 للعنصر الجديد. - تزيل
take_stock(inv, item, n)القيمةnوتُرجعTRUEعند توفر كمية كافية، وإلا فلا تغيّر شيئًا وتُرجعFALSE. - تُرجع
stock_of(inv, item)كمية المخزون، أو 0 للعنصر غير المعروف.
تغيّر الدوال المخزون في مكانه ولا تُرجعه. يقرأ الكود المقدم الأمرين add apple 5 وtake apple 2، ثم يطبع نتيجة كل عملية take، وبعد ذلك يطبع كل عنصر بالترتيب الأبجدي.
ضع الكود في Inventory.R. يحتوي main.R على كود الإدخال/الإخراج المقدم ولا يمكن تعديله.
جرّب بنفسك
source("Inventory.R")
# كود الإدخال/الإخراج المُزوَّد: اتركه كما هو
input <- suppressWarnings(readLines(file("stdin")))
inv <- new_inventory()
for (line in input) {
p <- strsplit(line, " ")[[1]]
n <- as.numeric(p[3])
if (p[1] == "add") add_stock(inv, p[2], n)
if (p[1] == "take") cat("take ", p[2], ": ", if (take_stock(inv, p[2], n)) "ok" else "not enough", "\n", sep = "")
}
for (item in sort(names(inv$items))) cat(item, ": ", stock_of(inv, item), "\n", sep = "")
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات S3
التعامل مع الملفاتالقوائم باستخدام فئةدوال المُنشئأساليب الطباعة والتنسيقأدوات التحقق والمساعدةمراجعة - درجات الحرارة2S3 الدوال العامة والطرق
الدوال العامة وUseMethodالطرق الافتراضيةطرق الدوال العامة الأساسيةأساسيات NextMethodمراجعة - مساحات الأشكالتدرّب بنفسك: مترجم R عبر الإنترنت