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