التوسعة باستخدام NextMethod
جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 14 من 57.
غالبًا ما تنفّذ طريقة الابن عمل طريقة الأب بالإضافة إلى القليل من العمل. تستدعي NextMethod() طريقة الأب، لذا يضيف الابن ما هو جديد فقط. الأجر الشهري للمدير هو أجر الموظف مضافًا إليه المكافأة:
pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
pay.manager <- function(x) NextMethod() + x$bonus / 12
m <- structure(list(salary = 60000, bonus = 12000), class = c("manager", "employee"))
e <- structure(list(salary = 36000), class = "employee")
cat(pay(e), pay(m))الناتج:
3000 6000تواصل NextMethod() العمل عبر عدة مستويات. تضيف كل طريقة جزءها وتُمرِّر التنفيذ إلى الفئة التي تلي فئتها:
pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
pay.manager <- function(x) NextMethod() + x$bonus / 12
pay.director <- function(x) NextMethod() + 500
d <- structure(list(salary = 120000, bonus = 24000),
class = c("director", "manager", "employee"))
print(pay(d))الناتج:
[1] 12500يمكن لطريقة الابن أيضًا أن تتحقق أولًا ولا تُمرّر التنفيذ إلا عند نجاح التحقق. تُعيد طريقة الوالد الكائن المُغيَّر مع متجه فئته الكامل، لذا تظل النتيجة حساب توفير:
withdraw <- function(acc, amount) UseMethod("withdraw")
withdraw.account <- function(acc, amount) {
if (amount > acc$balance) stop("insufficient funds", call. = FALSE)
acc$balance <- acc$balance - amount
acc
}
withdraw.savings <- function(acc, amount) {
if (amount > 500) stop("savings limit is 500", call. = FALSE)
NextMethod()
}
s <- structure(list(balance = 1000), class = c("savings", "account"))
s <- withdraw(s, 200)
cat(s$balance, class(s))الناتج:
800 savings accountتعيد المُنشئات والأساليب استخدام الصنف الأب بالطريقة نفسها: تستدعي new_manager() الدالة new_employee()، وتستدعي pay.manager() الدالة NextMethod(). يُكتب كود الموظف مرة واحدة، ويبني كل صنف فرعي عليه:
new_manager <- function(name, salary, bonus) {
new_employee(name, salary, bonus = bonus, class = "manager") # إعادة استخدام المُنشئ
}
pay.manager <- function(x) NextMethod() + x$bonus / 12 # إعادة استخدام الطريقةالتحدي
سهلالحسابات وحسابات التوفير موجودة في ملفين. في Account.R أكمل withdraw.account(acc, amount)، التي تتوقف مع insufficient funds عندما يكون المبلغ أكبر من الرصيد، وإلا تُرجع الحساب مع الرصيد الأقل، وformat.account()، التي تُرجع ada: 800. في Savings.R أكمل withdraw.savings()، التي تتوقف مع savings limit is 500 للمبالغ الأكبر من 500، وإلا تتابع باستخدام NextMethod()، وformat.savings()، التي تُرجع ada: 800 (savings) من خلال استدعاء NextMethod().
استخدم call. = FALSE. الدالة العامة والمنشئات معطاة. يقرأ الكود المقدم savings ada 1000 أو account bo 300، ثم مبالغ السحب؛ ويطبع withdrew 200 أو refused: والرسالة، وأخيرًا الحساب المنسق.
ضع الكود في Account.R وSavings.R. يحتوي main.R على كود الإدخال/الإخراج المقدم ولا يمكن تعديله.
جرّب بنفسك
source("Account.R")
source("Savings.R")
# كود الإدخال/الإخراج المُزوَّد: اتركه كما هو
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], " ")[[1]]
acc <- if (p[1] == "savings") new_savings(p[2], as.numeric(p[3])) else new_account(p[2], as.numeric(p[3]))
for (amount in as.numeric(input[-1])) {
acc <- tryCatch({
acc <- withdraw(acc, amount)
cat("withdrew ", amount, "\n", sep = "")
acc
}, error = function(e) {
cat("refused: ", conditionMessage(e), "\n", sep = "")
acc
})
}
cat(format(acc), "\n", sep = "")
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات S3
التعامل مع الملفاتالقوائم باستخدام فئةدوال المُنشئأساليب الطباعة والتنسيقأدوات التحقق والمساعدةمراجعة - درجات الحرارة2S3 الدوال العامة والطرق
الدوال العامة وUseMethodالطرق الافتراضيةطرق الدوال العامة الأساسيةأساسيات NextMethodمراجعة - مساحات الأشكال3وراثة S3
متجهات الأصنافترتيب البحث عن الأساليبالتوسعة باستخدام NextMethodالتحقق باستخدام inherits()مراجعة - رواتب الموظفينتدرّب بنفسك: مترجم R عبر الإنترنت