اختيار الطريقة بناءً على وسيطين
جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 29 من 57.
يمكن لـ S4 generic اختيار أسلوبها وفقًا لفئات عدة وسائط. تسرد التوقيعة فئة واحدة لكل وسيط، ولذلك يمكن أن يكون لكل زوج من الفئات أسلوبه الخاص:
setClass("Asteroid", slots = c(size = "numeric"))
setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Asteroid", "Ship"), function(a, b) paste(b@name, "is hit"))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
rock <- new("Asteroid", size = 3)
enterprise <- new("Ship", name = "Enterprise")
print(collide(rock, enterprise))
print(collide(enterprise, enterprise))المخرجات:
[1] "Enterprise is hit"
[1] "two ships bump"الفئة "ANY" تطابق كل فئة. والطريقة الخاصة بـ signature("ANY", "ANY") هي البديل الاحتياطي الذي يُشغَّل عندما لا يناسب أي زوج أكثر تحديدًا:
setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
setMethod("collide", signature("ANY", "ANY"), function(a, b) "nothing happens")
s <- new("Ship", name = "A")
cat(collide(s, s), "/", collide(s, 42), "/", collide("x", "y"))الناتج:
two ships bump / nothing happens / nothing happensترتيب الوسائط مهم: signature("A", "B") وsignature("B", "A") طريقتان مختلفتان. يمكن أن تظهر الفئات الأساسية مثل numeric وcharacter في التوقيع أيضًا:
invisible(setGeneric("join", function(x, y) standardGeneric("join")))
setMethod("join", signature("character", "numeric"), function(x, y) paste(x, "number", y))
setMethod("join", signature("numeric", "character"), function(x, y) paste(y, "after number", x))
print(join("item", 3))
print(join(3, "item"))الناتج:
[1] "item number 3"
[1] "item after number 3"الصنف "missing" في التوقيع يطابق وسيطًا لم يُمرَّر إطلاقًا، لذا يمكن لدالة عامة واحدة أن توفر صيغة قصيرة وأخرى طويلة:
invisible(setGeneric("greet", function(name, greeting) standardGeneric("greet")))
setMethod("greet", signature("character", "missing"), function(name, greeting) paste("Hello,", name))
setMethod("greet", signature("character", "character"), function(name, greeting) paste0(greeting, ", ", name))
print(greet("Ada"))
print(greet("Ada", "Good morning"))الناتج:
[1] "Hello, Ada"
[1] "Good morning, Ada"التحدي
سهلتعتمد أسعار الشحن على العنصر والمنطقة. تُعلن الفئات في Item.R (Letter وBox، ولكل منهما خانة kg) وفي Zone.R (Domestic وAbroad، ولكل منهما خانة name). في Rates.R أنشئ العام shipping(item, zone) وطريقة واحدة لكل زوج:
- العنصر
Letterفي المنزل: 1؛ وفي الخارج: 3. - العنصر
Boxفي المنزل: 5 زائد 2 لكل كجم؛ وفي الخارج: 12 زائد 4 لكل كجم. - أي زوج آخر: أوقف التنفيذ باستخدام
no rate for this item and zone(استخدمcall. = FALSE).
يقرأ الكود المُقدَّم الأسطر box home 2.5 (العنصر، المنطقة، الكيلوجرامات)، حيث تبقى الكلمات غير المعروفة نصًا عاديًا، ويطبع box to home: 10.00 أو error: والرسالة.
ضع الكود الخاص بك في Item.R وZone.R وRates.R. يحتوي main.R على كود الإدخال/الإخراج المُقدَّم ولا يمكن تعديله.
جرّب بنفسك
source("Item.R")
source("Zone.R")
source("Rates.R")
# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
kg <- as.numeric(p[3])
item <- switch(p[1], letter = new("Letter", kg = kg), box = new("Box", kg = kg), kg)
zone <- switch(p[2], home = new("Domestic", name = "home"), abroad = new("Abroad", name = "abroad"), p[2])
out <- tryCatch(sprintf("%s to %s: %.2f", p[1], p[2], shipping(item, zone)),
error = function(e) paste("error:", conditionMessage(e)))
cat(out, "\n", sep = "")
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات S3
التعامل مع الملفاتالقوائم باستخدام فئةدوال المُنشئأساليب الطباعة والتنسيقأدوات التحقق والمساعدةمراجعة - درجات الحرارة2S3 الدوال العامة والطرق
الدوال العامة وUseMethodالطرق الافتراضيةطرق الدوال العامة الأساسيةأساسيات NextMethodمراجعة - مساحات الأشكال3وراثة S3
متجهات الأصنافترتيب البحث عن الأساليبالتوسعة باستخدام NextMethodالتحقق باستخدام inherits()مراجعة - رواتب الموظفين6S4 الدوال العامة والطرق
إنشاء الدوال العامةالطرق للدوال المضمّنةاختيار الطريقة بناءً على وسيطينsetValidity و validObjectمراجعة - المال والعملةتدرّب بنفسك: مترجم R عبر الإنترنت