الإغلاقات ككائنات
جزء من قسم البرمجة كائنية التوجه في رحلة 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التحدي
سهلأكمل دالة المصنع 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 = "")
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات S3
التعامل مع الملفاتالقوائم باستخدام فئةدوال المُنشئأساليب الطباعة والتنسيقأدوات التحقق والمساعدةمراجعة - درجات الحرارة2S3 الدوال العامة والطرق
الدوال العامة وUseMethodالطرق الافتراضيةطرق الدوال العامة الأساسيةأساسيات NextMethodمراجعة - مساحات الأشكالتدرّب بنفسك: مترجم R عبر الإنترنت