ترتيب البحث عن الأساليب
جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 13 من 57.
في كل استدعاء، يستعرض R متجه الفئات من اليسار إلى اليمين ويشغّل أول طريقة يعثر عليها. إذا لم تكن لدى أي فئة طريقة، فإنه يستخدم الطريقة الافتراضية. يمكن للكائنات المختلفة في تسلسل هرمي واحد أن تتوقف عند مستويات مختلفة:
move <- function(x) UseMethod("move")
move.animal <- function(x) "walks"
move.bird <- function(x) "flies"
move.default <- function(x) "stays"
penguin <- structure(list(), class = c("penguin", "bird", "animal"))
dog <- structure(list(), class = c("dog", "animal"))
rock <- structure(list(), class = "rock")
cat(move(penguin), move(dog), move(rock))الناتج:
flies walks staysيتجاوز الطفل طريقةً في الأصل بإعادة تعريفها بطريقته الخاصة. يؤثر التجاوز في الطفل فقط وفي كل ما يندرج تحته؛ بينما يحتفظ الأصل وأطفاله الآخرون بطريقة الأصل:
move <- function(x) UseMethod("move")
move.animal <- function(x) "walks"
move.bird <- function(x) "flies"
move.penguin <- function(x) "swims"
penguin <- structure(list(), class = c("penguin", "bird", "animal"))
sparrow <- structure(list(), class = c("bird", "animal"))
cat(move(penguin), move(sparrow))الناتج:
swims fliesيتم البحث عن كل generic بشكل مستقل. يمكن لكائن واحد أن يأخذ sound() من فئته الخاصة وmove() من فئة أب، ويمكن لطريقة الأب استدعاء generics أخرى تُجري التوزيع على الابن مرة أخرى:
sound <- function(x) UseMethod("sound")
move <- function(x) UseMethod("move")
describe <- function(x) UseMethod("describe")
sound.animal <- function(x) "..."
sound.dog <- function(x) "woof"
move.animal <- function(x) "walks"
describe.animal <- function(x) paste(x$name, "says", sound(x), "and", move(x))
rex <- structure(list(name = "Rex"), class = c("dog", "animal"))
print(describe(rex))الناتج:
[1] "Rex says woof and walks"بالنسبة إلى كائن له سمة فئة، ينظر التوزيع إلى تلك السمة فقط ثم إلى الافتراضي. لا يزال الكائن قائمةً من الداخل، لكن لا تتم تجربة طريقة لـ list:
size <- function(x) UseMethod("size")
size.list <- function(x) "a list"
size.default <- function(x) "default"
bag <- structure(list(1, 2), class = "bag")
cat(size(list(1, 2)), "/", size(bag))الناتج:
a list / defaultالتحدي
سهلالمربع هو مستطيل ذو أضلاع متساوية. في Rectangle.R اكتب الدوال area.rectangle() وperimeter.rectangle() وname.rectangle()، والتي تُرجع rectangle 2x3. في Square.R أكمل new_square(side)، التي تستدعي new_rectangle() مع الفئة square، وتجاوز فقط name() باستخدام name.square()، والتي تُرجع square 2. يجب أن تستخدم المربعات الدالتين area() وperimeter() الخاصتين بالمستطيل.
الدوال العامة وnew_rectangle() مُعطاة. يقرأ الكود المُقدَّم أسطرًا تحتوي على رقمين (مستطيل) أو رقم واحد (مربع)، ويطبع square 2: area 4, perimeter 8.
يجب وضع الكود الخاص بك في Rectangle.R وSquare.R. يحتوي main.R على كود الإدخال/الإخراج المُقدَّم، ولا يمكن تعديله.
جرّب بنفسك
source("Rectangle.R")
source("Square.R")
# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
n <- as.numeric(strsplit(line, " ")[[1]])
s <- if (length(n) == 1) new_square(n[1]) else new_rectangle(n[1], n[2])
cat(name(s), ": area ", area(s), ", perimeter ", perimeter(s), "\n", sep = "")
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات S3
التعامل مع الملفاتالقوائم باستخدام فئةدوال المُنشئأساليب الطباعة والتنسيقأدوات التحقق والمساعدةمراجعة - درجات الحرارة2S3 الدوال العامة والطرق
الدوال العامة وUseMethodالطرق الافتراضيةطرق الدوال العامة الأساسيةأساسيات NextMethodمراجعة - مساحات الأشكال3وراثة S3
متجهات الأصنافترتيب البحث عن الأساليبالتوسعة باستخدام NextMethodالتحقق باستخدام inherits()مراجعة - رواتب الموظفينتدرّب بنفسك: مترجم R عبر الإنترنت