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

إنشاء الدوال العامة

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

يتم إنشاء دالة عامة من النوع S4 باستخدام setGeneric(). ويكون جسمها هو standardGeneric("name")، وهو النظير في S4 لـ UseMethod(). تُرجع setGeneric() اسم الدالة العامة، والذي تتم طباعته عند استدعائها في المستوى الأعلى:

setGeneric("area", function(shape) standardGeneric("area"))

الناتج:

[1] "area"

غلّف الاستدعاء بـ invisible() لإبقاء هذا السطر خارج الناتج. ثم يضيف setMethod("area", "Circle", ...) الطريقة لفئة واحدة:

setClass("Circle", slots = c(r = "numeric"))
setClass("Square", slots = c(side = "numeric"))
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
setMethod("area", "Square", function(shape) shape@side^2)
cat(area(new("Circle", r = 1)), area(new("Square", side = 3)))

الناتج:

3.141593 9

للطريقة نفس الوسائط التي يملكها العام. عندما يحتوي العام على ...، يمكن للطريقة إضافة وسائط مُسمّاة خاصة بها بعد تلك الوسائط:

setClass("Circle", slots = c(r = "numeric"))
invisible(setGeneric("describe", function(x, ...) standardGeneric("describe")))
setMethod("describe", "Circle", function(x, ..., digits = 2) {
  paste("circle of area", round(pi * x@r^2, digits))
})
c1 <- new("Circle", r = 2)
print(describe(c1))
print(describe(c1, digits = 4))

الناتج:

[1] "circle of area 12.57"
[1] "circle of area 12.5664"

تحتاج setMethod() إلى وجود الدالة العامة مسبقًا، لذلك تتم معالجة الملف الذي يحتوي على setGeneric() أولًا. يؤدي استدعاء فئة لا تحتوي على أسلوب إلى إيقاف التنفيذ مع ظهور خطأ يذكر التوقيع:

invisible(setGeneric("area", function(shape) standardGeneric("area")))
setClass("Circle", slots = c(r = "numeric"))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
area(42)

الناتج:

Error: unable to find an inherited method for function ‘area’ for signature ‘shape = "numeric"’
Execution halted
challenge icon

التحدي

سهل

الأشكال هي أصناف S4 في ثلاثة ملفات. في Shape.R أنشئ الدوال العامة area(shape) وperimeter(shape) باستخدام setGeneric()، مع تغليفها داخل invisible(). في Circle.R وSquare.R يتم التصريح عن الأصناف؛ أضف طريقتَي area وperimeter لكل صنف باستخدام setMethod().

يقرأ الكود المقدم السطرين circle 2 أو square 3 ويطبع circle: area 12.57, perimeter 12.57.

ضع الكود الخاص بك في Shape.R وCircle.R وSquare.R. يحتوي main.R على كود الإدخال/الإخراج المقدم، ولا يمكن تعديله.

جرّب بنفسك

source("Shape.R")
source("Circle.R")
source("Square.R")

# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  s <- if (p[1] == "circle") new("Circle", r = as.numeric(p[2])) else new("Square", side = as.numeric(p[2]))
  cat(sprintf("%s: area %.2f, perimeter %.2f", p[1], area(s), perimeter(s)), "\n", sep = "")
}
quiz iconاختبر نفسك

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

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

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