الإغلاقات ككائنات
جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 17 من 57.
تعرّفت على الإغلاقات في المنطق والتدفّق: الدالة المُنشأة داخل دالة أخرى تحتفظ بالمتغيرات المحيطة بها. إن مصنع الدوال الذي يُرجع قائمة من هذه الدوال ينشئ كائنًا. متغيراته المحلية هي بيانات الكائن، والدوال هي أساليبه:
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() القيمة.
يقرأ الكود المرفق قيمة البداية، ثم الأوامر + أو - أو reset، ويطبع القيمة بعد كل أمر. وفي النهاية يطبع الأسماء الموجودة في القائمة المُرجعة، والتي يجب أن تقتصر على الدوال الأربع.
ضع الكود في Counter.R. يحتوي main.R على كود الإدخال/الإخراج المرفق، ولا يمكن تعديله.
جرّب بنفسك
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 عبر الإنترنت