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

callNextMethod

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

داخل طريقة S4، تستدعي callNextMethod() طريقة الفئة الأصلية باستخدام الوسائط نفسها وتُرجع نتيجتها. تبني طريقة الفئة الابنة على إجابة الفئة الأصلية بدلًا من تكرارها:

setClass("Employee", slots = c(name = "character", salary = "numeric"))
setClass("Manager", contains = "Employee", slots = c(reports = "numeric"))
invisible(setGeneric("describe", function(x) standardGeneric("describe")))
setMethod("describe", "Employee", function(x) paste(x@name, "earns", x@salary))
setMethod("describe", "Manager", function(x) paste(callNextMethod(), "and manages", x@reports))
print(describe(new("Manager", name = "Ada", salary = 60000, reports = 4)))

الناتج:

[1] "Ada earns 60000 and manages 4"

ينطبق الأمر نفسه على show() أيضًا: يطبع الابن أسطر الوالد ثم أسطره الخاصة:

setClass("Employee", slots = c(name = "character"))
setClass("Manager", contains = "Employee", slots = c(reports = "numeric"))
setMethod("show", "Employee", function(object) cat("Employee:", object@name, "\n"))
setMethod("show", "Manager", function(object) {
  callNextMethod()
  cat("Reports:", object@reports, "\n")
})
new("Manager", name = "Ada", reports = 4)

الناتج:

Employee: Ada 
Reports: 4 

تستدعي new() الدالة العامة initialize(). ويمكن لطريقة مخصّصة لها أن تملأ الخانات التي يتم تحديدها استنادًا إلى خانات أخرى. وهي تستدعي callNextMethod(.Object, ...) أولًا، ولذلك يظل الإعداد العادي وفحص الصلاحية قائمين:

setClass("Order", slots = c(prices = "numeric", total = "numeric"))
setMethod("initialize", "Order", function(.Object, ...) {
  .Object <- callNextMethod(.Object, ...)
  .Object@total <- sum(.Object@prices)
  .Object
})
o <- new("Order", prices = c(2.5, 4, 1))
print(o@total)

الناتج:

[1] 7.5

مثل NextMethod() في S3، تتسلسل callNextMethod() عبر عدة مستويات، حيث يضيف كل صنف الجزء الخاص به:

setClass("Ticket", slots = c(base = "numeric"))
setClass("Vip", contains = "Ticket")
setClass("Backstage", contains = "Vip")
invisible(setGeneric("price", function(t) standardGeneric("price")))
setMethod("price", "Ticket", function(t) t@base)
setMethod("price", "Vip", function(t) callNextMethod() * 2)
setMethod("price", "Backstage", function(t) callNextMethod() + 50)
cat(price(new("Ticket", base = 30)), price(new("Vip", base = 30)), price(new("Backstage", base = 30)))

الناتج:

30 60 110
challenge icon

التحدي

سهل

تأتي التذاكر في ثلاثة مستويات، وكل مستوى منها في ملفه الخاص. تم التصريح بالفئات والدالة العامة price(). أضف الأساليب:

  • Ticket.R: تُساوي price() السعر الأساسي؛ وتطبع show() العبارة Ticket for gala وسطرًا جديدًا.
  • Vip.R: تُساوي price() 1.5 من سعر التذكرة؛ وتطبع show() سطر التذكرة ثم VIP lounge access.
  • Backstage.R: تُساوي price() سعر VIP مضافًا إليه 50؛ وتطبع show() أسطر VIP ثم Backstage pass.

استخدم callNextMethod() في أساليب الفئات الفرعية. يقرأ الكود المُقدَّم الأسطر vip gala 80 (المستوى، والفعالية، والسعر الأساسي) ويطبع كل تذكرة وسعرها.

ضع الكود في Ticket.R وVip.R وBackstage.R. يحتوي main.R على كود الإدخال/الإخراج المُقدَّم، ولا يمكن تعديله.

جرّب بنفسك

source("Ticket.R")
source("Vip.R")
source("Backstage.R")

# كود الإدخال/الإخراج المُزوَّد: اتركه كما هو
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  base <- as.numeric(p[3])
  t <- switch(p[1],
    standard = new("Ticket", event = p[2], base = base),
    vip = new("VipTicket", event = p[2], base = base),
    backstage = new("BackstageTicket", event = p[2], base = base))
  print(t)
  cat(sprintf("price: %.2f", price(t)), "\n", sep = "")
}
quiz iconاختبر نفسك

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

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

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