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

اختيار الطريقة بناءً على وسيطين

جزء من قسم البرمجة كائنية التوجه في رحلة 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"
challenge icon

التحدي

سهل

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

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

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

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