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

الأصناف الافتراضية

جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 34 من 57.

تصف الفئة الافتراضية ما تشترك فيه عائلة من الفئات، ولا يمكن أن تمتلك كائنات خاصة بها. صرّح عنها باستخدام representation("VIRTUAL")؛ وتستخدم فئاتها الفرعية contains كالمعتاد:

setClass("Shape", representation("VIRTUAL"))
setClass("Circle", contains = "Shape", slots = c(r = "numeric"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
cat(isVirtualClass("Shape"), is(new("Circle", r = 1), "Shape"), "\n")
cat(tryCatch({ new("Shape"); "made" }, error = function(e) "not allowed"), "\n")

الناتج:

TRUE TRUE 
not allowed 

تعمل طريقة للفئة الافتراضية مع كل فئة فرعية. هنا تستدعي describe() الخاصة بـ Shape الدالة area()، التي تنفذها كل فئة فرعية، لذا تُكتب الوصف مرة واحدة:

setClass("Shape", representation("VIRTUAL"))
setClass("Circle", contains = "Shape", slots = c(r = "numeric"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
invisible(setGeneric("area", function(s) standardGeneric("area")))
invisible(setGeneric("describe", function(s) standardGeneric("describe")))
setMethod("area", "Circle", function(s) pi * s@r^2)
setMethod("area", "Square", function(s) s@side^2)
setMethod("describe", "Shape", function(s) sprintf("%s with area %.2f", class(s), area(s)))
for (s in list(new("Circle", r = 1), new("Square", side = 2))) cat(describe(s), "\n")

الناتج:

Circle with area 3.14 
Square with area 4.00 

يمكن لصنف افتراضي أن يعلن عن خانات، والتي يمتلكها كل صنف فرعي بعد ذلك:

setClass("Shape", representation("VIRTUAL", label = "character"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
sq <- new("Square", label = "tile", side = 2)
print(slotNames("Square"))

الناتج:

[1] "side"  "label"

setClassUnion() ينشئ فئة افتراضية من الفئات الموجودة. تقبل خانة من هذا النوع أيًّا منها، مثل جهة اتصال تكون إما عنوان بريد إلكتروني أو رقم هاتف:

setClassUnion("Contact", c("character", "numeric"))
setClass("Friend", slots = c(name = "character", contact = "Contact"))
a <- new("Friend", name = "Ada", contact = "ada@x.org")
b <- new("Friend", name = "Bo", contact = 5550123)
cat(class(a@contact), class(b@contact), "\n")
cat(tryCatch({ new("Friend", name = "Cy", contact = TRUE); "ok" }, error = function(e) "refused"), "\n")

الناتج:

character numeric 
refused 
challenge icon

التحدي

سهل

تشترك المدفوعات في الفئة الافتراضية Payment (الخانة amount) والدالتين العامتين fee() وreceipt()، وجميعها موجودة في Payment.R. أكمل ما يلي:

  • في Payment.R، طريقة receipt() للفئة Payment: card: 100.00 + 2.00 fee، بحيث تُبنى من اسم الفئة بأحرف صغيرة، وamount وfee()؛
  • في Card.R، الفئة Card (التي تحتوي على Payment) وطريقة fee() الخاصة بها: 2% من المبلغ؛
  • في Cash.R، الفئة Cash وطريقة fee() الخاصة بها: 0.

يقرأ الكود المزوَّد الأسطر card 100 أو cash 20، ويطبع إيصال كل دفعة وإجمالي المبلغ المفروض، ثم يتحقق من أن Payment افتراضية ولا يمكن إنشاؤها.

ضع الكود الخاص بك في Payment.R وCard.R وCash.R. يحتوي main.R على كود الإدخال/الإخراج المزوَّد، ولا يمكن تعديله.

جرّب بنفسك

source("Payment.R")
source("Card.R")
source("Cash.R")

# كود الإدخال/الإخراج المُزوَّد: اتركه كما هو
input <- suppressWarnings(readLines(file("stdin")))
total <- 0
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  amount <- as.numeric(p[2])
  pay <- switch(p[1], card = new("Card", amount = amount), cash = new("Cash", amount = amount))
  cat(receipt(pay), "\n", sep = "")
  total <- total + amount + fee(pay)
}
cat(sprintf("charged: %.2f", total), "\n", sep = "")
cat("Payment is virtual: ", isVirtualClass("Payment"), "\n", sep = "")
cat(tryCatch({ new("Payment", amount = 1); "created a Payment" }, error = function(e) "cannot create a Payment"), "\n", sep = "")
quiz iconاختبر نفسك

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

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

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