Menu
CoddyTech

التوسعة باستخدام contains

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

contains = "Animal" يجعل فئة S4 جديدة فئةً فرعية من Animal. تحتوي الفئة الفرعية على كل خانات الفئة الأصلية بالإضافة إلى خاناتها الخاصة، وتأخذ new() جميعها:

setClass("Animal", slots = c(name = "character", age = "numeric"))
setClass("Dog", contains = "Animal", slots = c(breed = "character"))
rex <- new("Dog", name = "Rex", age = 3, breed = "collie")
print(slotNames("Dog"))
cat(rex@name, rex@breed)

الناتج:

[1] "breed" "name"  "age"  
Rex collie

الأساليب المكتوبة للفئة الأب تعمل أيضًا مع الفئة الابنة. عندما لا تكون هناك طريقة للنوع العام Dog، يستخدم S4 الطريقة الخاصة بـ Animal:

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
invisible(setGeneric("intro", function(a) standardGeneric("intro")))
setMethod("intro", "Animal", function(a) paste("I am", a@name))
print(intro(new("Dog", name = "Rex")))

الناتج:

[1] "I am Rex"

تتجاوز الفئة الفرعية طريقةً في الفئة الأصلية عبر تعريف طريقتها الخاصة للمعمّم نفسه. تفوز الفئة الأكثر تحديدًا، وتحتفظ الفئات الفرعية الأخرى بطريقة الفئة الأصلية:

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Cat", contains = "Animal")
invisible(setGeneric("sound", function(a) standardGeneric("sound")))
setMethod("sound", "Animal", function(a) "...")
setMethod("sound", "Dog", function(a) "woof")
cat(sound(new("Dog", name = "Rex")), sound(new("Cat", name = "Tom")))

المخرجات:

woof ...

تكون is(x, "Animal") مساويةً لـ TRUE بالنسبة إلى كلب، وتقبل الخانة المعرّفة على أنها "Animal" كائنًا من النوع Dog. يعمل الكود المكتوب للفئة الأب مع كل فئة فرعية:

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Owner", slots = c(pet = "Animal"))
rex <- new("Dog", name = "Rex")
o <- new("Owner", pet = rex)
cat(is(rex, "Animal"), is(o@pet, "Dog"))

الناتج:

TRUE TRUE
challenge icon

التحدي

سهل

الموظفون والمديرون أصناف S4 موزعة على ملفين. يعرّف Employee.R الصنف Employee (الفتحات name وsalary) والواجهة العامة describe()، ويحتاج إلى طريقة للصنف Employee تُرجع Bo earns 40000. في Manager.R عرّف الصنف Manager، الذي يحتوي على Employee ويضيف الفتحة reports (رقمية)، وأعد تعريف describe() بحيث تُرجع Ada earns 60000 and manages 4.

يقرأ الكود المقدّم أسطرًا مثل employee Bo 40000 أو manager Ada 60000 4 ويطبع describe()، وما إذا كان الكائن موظفًا، وفتحاته.

ضع كودك في Employee.R وManager.R. يحتوي main.R على كود الإدخال/الإخراج المقدّم ولا يمكن تعديله.

جرّب بنفسك

source("Employee.R")
source("Manager.R")

# كود الإدخال والإخراج المقدَّم: اتركه كما هو
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  x <- if (p[1] == "manager") {
    new("Manager", name = p[2], salary = as.numeric(p[3]), reports = as.numeric(p[4]))
  } else {
    new("Employee", name = p[2], salary = as.numeric(p[3]))
  }
  cat(describe(x), "\n", sep = "")
  cat("is an employee: ", is(x, "Employee"), ", slots: ", paste(slotNames(x), collapse = ", "), "\n", sep = "")
}
quiz iconاختبر نفسك

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

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

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