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

الدوال العامة و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
challenge icon

التحدي

سهل

يتم تقسيم الأشكال على ثلاثة ملفات. أكمل الدالة العامة 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 = "")
}
quiz iconاختبر نفسك

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

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

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