Menu
Coddy logo textTech

Estendere con contains

Fa parte della sezione Programmazione orientata agli oggetti del percorso R di Coddy. Lezione 32 di 57.

contains = "Animal" rende una nuova classe S4 una sottoclasse di Animal. La sottoclasse ha tutti gli slot della classe padre più i propri, e new() li accetta tutti:

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)

Output:

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

I metodi scritti per la classe genitore funzionano anche per la classe figlia. Quando un generico non ha un metodo per Dog, S4 usa quello per 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")))

Output:

[1] "I am Rex"

Una classe figlia ridefinisce un metodo della classe genitore definendone uno proprio per lo stesso generico. Vince la classe più specifica, mentre le altre sottoclassi mantengono il metodo della classe genitore:

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")))

Output:

woof ...

is(x, "Animal") è TRUE per un cane e uno slot dichiarato come "Animal" accetta un Dog. Il codice scritto per la classe genitore funziona con tutte le sottoclassi:

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"))

Output:

TRUE TRUE
challenge icon

Sfida

Facile

Dipendenti e manager sono classi S4 in due file. Employee.R dichiara Employee (slot name, salary) e il generico describe(), e necessita di un metodo per Employee che restituisca Bo earns 40000. In Manager.R dichiara Manager, che contiene Employee e aggiunge lo slot reports (numerico), e sovrascrivi describe() in modo che restituisca Ada earns 60000 and manages 4.

Il codice fornito legge righe employee Bo 40000 oppure manager Ada 60000 4 e stampa describe(), se l'oggetto è un dipendente e i suoi slot.

Il tuo codice va in Employee.R e Manager.R. main.R contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

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

# Supplied input/output code: keep it as it is
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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore R online