الدوال العامة وUseMethod
جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 7 من 57.
الدالة العامة هي دالة يكون متنها UseMethod("name"). عند استدعائها، تنظر إلى فئة وسيطها الأول وتستدعي الطريقة name.class. تعمل print() وformat() بهذه الطريقة؛ ويمكنك كتابة دوال عامة خاصة بك أيضًا:
speak <- function(x) UseMethod("speak")
speak.dog <- function(x) paste(x$name, "says woof")
speak.cat <- function(x) paste(x$name, "says meow")
rex <- structure(list(name = "Rex"), class = "dog")
tom <- structure(list(name = "Tom"), class = "cat")
print(speak(rex))
print(speak(tom))الناتج:
[1] "Rex says woof"
[1] "Tom says meow"يكتب المستدعي استدعاءً واحدًا، ويستجيب كل كائن بطريقته الخاصة. هذا هو تعدد الأشكال: لا يحتاج الكود الذي يكرّر عبر قائمة مختلطة إلى if لكل صنف:
speak <- function(x) UseMethod("speak")
speak.dog <- function(x) paste(x$name, "says woof")
speak.cat <- function(x) paste(x$name, "says meow")
pets <- list(structure(list(name = "Rex"), class = "dog"),
structure(list(name = "Tom"), class = "cat"),
structure(list(name = "Bo"), class = "dog"))
for (p in pets) cat(speak(p), "\n")الناتج:
Rex says woof
Tom says meow
Bo says woof تأخذ الطريقة وسائط الدالة العامة. أضف إلى الدالة العامة وسيطًا ... كي تتمكن الطرق من قبول وسائط إضافية خاصة بها، مثل digits للدائرة:
area <- function(shape, ...) UseMethod("area")
area.square <- function(shape, ...) shape$side^2
area.circle <- function(shape, digits = 2, ...) round(pi * shape$r^2, digits)
sq <- structure(list(side = 3), class = "square")
ci <- structure(list(r = 1), class = "circle")
print(area(sq))
print(area(ci))
print(area(ci, digits = 4))الناتج:
[1] 9
[1] 3.14
[1] 3.1416تُمرّر UseMethod() الاستدعاء إلى الطريقة ولا تعود أبدًا: ما تُرجعه الطريقة هو نتيجة الدالة العامة، ولا يُنفَّذ الكود بعد UseMethod(). لذلك تتكوّن الدالة العامة من سطر واحد:
size <- function(x) {
UseMethod("size")
cat("this line never runs\n")
}
size.box <- function(x) x$w * x$h
b <- structure(list(w = 2, h = 5), class = "box")
print(size(b))الناتج:
[1] 10التحدي
سهلتُقسَّم الأشكال على ثلاثة ملفات. أكمل الدالة العامة area() في Shape.R، ثم أضف الطريقتين area.circle() (ط π مضروبًا في مربع نصف القطر) في Circle.R وarea.rectangle() (العرض مضروبًا في الارتفاع) في Rectangle.R. المُنشئات مُعطاة.
يقرأ الكود المقدَّم أسطرًا مثل circle 2 أو rectangle 3 4، ويطبع فئة كل شكل ومساحته بمنزلتين عشريتين: circle: 12.57.
ضع الكود في Shape.R وCircle.R وRectangle.R. يحتوي main.R على كود الإدخال/الإخراج المقدَّم، ولا يمكن تعديله.
جرّب بنفسك
source("Shape.R")
source("Circle.R")
source("Rectangle.R")
# كود الإدخال/الإخراج المزوّد: اتركه كما هو
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
s <- if (p[1] == "circle") new_circle(as.numeric(p[2])) else new_rectangle(as.numeric(p[2]), as.numeric(p[3]))
cat(sprintf("%s: %.2f", class(s), area(s)), "\n", sep = "")
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات S3
التعامل مع الملفاتالقوائم باستخدام فئةدوال المُنشئأساليب الطباعة والتنسيقأدوات التحقق والمساعدةمراجعة - درجات الحرارة2S3 الدوال العامة والطرق
الدوال العامة وUseMethodالطرق الافتراضيةطرق الدوال العامة الأساسيةأساسيات NextMethodمراجعة - مساحات الأشكالتدرّب بنفسك: مترجم R عبر الإنترنت