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

الإغلاقات ككائنات

جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 17 من 57.

تعرّفتَ على الإغلاقات في Logic & Flow: فالدالة المُنشأة داخل دالة أخرى تحتفظ بالمتغيرات المحيطة بها. إن مصنع الدوال الذي يعيد قائمة من هذه الدوال يبني كائنًا. ومتغيراته المحلية هي بيانات الكائن، بينما الدوال هي أساليبه:

make_account <- function(balance = 0) {
  deposit <- function(x) balance <<- balance + x
  get_balance <- function() balance
  list(deposit = deposit, get_balance = get_balance)
}
acc <- make_account(100)
acc$deposit(50)
print(acc$get_balance())

المخرجات:

[1] 150

كل استدعاء للمصنِّع يشغّل جسمه مرة أخرى، لذلك يحصل كل كائن على متغيراته الخاصة. تغيير حساب واحد لا يؤثر في الحساب الآخر:

make_account <- function(balance = 0) {
  list(deposit = function(x) balance <<- balance + x,
       get_balance = function() balance)
}
ada <- make_account(100)
bo <- make_account(5)
ada$deposit(1)
cat(ada$get_balance(), bo$get_balance())

الناتج:

101 5

البيانات خاصة. لا يُعد balance عنصرًا في القائمة، لذا فإن acc$balance تساوي NULL، وإسناد قيمة إليها يضيف فقط عنصرًا غير ذي صلة. الدوال الموجودة في القائمة هي الواجهة العامة الكاملة للكائن:

make_account <- function(balance = 0) {
  list(get_balance = function() balance)
}
acc <- make_account(100)
print(acc$balance)
acc$balance <- 1e6
print(acc$get_balance())

الناتج:

NULL
[1] 100

يمكن للطرق استدعاء بعضها بعضًا عندما يتم تعريفها كدوال محلية قبل إنشاء القائمة. هنا تعيد add_many() استخدام add():

make_tally <- function() {
  total <- 0
  add <- function(x) total <<- total + x
  add_many <- function(xs) for (x in xs) add(x)
  get <- function() total
  list(add = add, add_many = add_many, get = get)
}
t <- make_tally()
t$add(1)
t$add_many(c(2, 3, 4))
print(t$get())

الناتج:

[1] 10
challenge icon

التحدي

سهل

أكمل دالة المصنع make_counter(start = 0) في Counter.R. فهي تُبقي القيمة الحالية خاصة وتُرجع قائمة تحتوي على أربع دوال: تغيّر increment() وdecrement() القيمة بمقدار 1، وتعيد reset() القيمة إلى start، بينما تُرجع value() القيمة.

يقرأ الكود المُ provided قيمة البدء، ثم الأوامر + أو - أو reset، ويطبع القيمة بعد كل أمر. وفي النهاية يطبع أسماء العناصر في القائمة المُرجعة، والتي يجب أن تحتوي فقط على الدوال الأربع.

ضع الكود الخاص بك في Counter.R. يحتوي main.R على كود الإدخال/الإخراج المُ provided ولا يمكن تعديله.

جرّب بنفسك

source("Counter.R")

# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
input <- suppressWarnings(readLines(file("stdin")))
counter <- make_counter(as.numeric(input[1]))
for (cmd in input[-1]) {
  if (cmd == "+") counter$increment()
  if (cmd == "-") counter$decrement()
  if (cmd == "reset") counter$reset()
  cat(cmd, " -> ", counter$value(), "\n", sep = "")
}
cat("fields visible: ", paste(sort(names(counter)), collapse = ", "), "\n", sep = "")
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم R عبر الإنترنت