Menu
Coddy logo textTech

Ordine di ricerca dei metodi

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

A ogni chiamata, R percorre il vettore delle classi da sinistra a destra ed esegue il primo metodo che trova. Se nessuna classe ha un metodo, usa quello predefinito. Oggetti diversi in una stessa gerarchia possono fermarsi a livelli diversi:

move <- function(x) UseMethod("move")
move.animal <- function(x) "walks"
move.bird <- function(x) "flies"
move.default <- function(x) "stays"
penguin <- structure(list(), class = c("penguin", "bird", "animal"))
dog <- structure(list(), class = c("dog", "animal"))
rock <- structure(list(), class = "rock")
cat(move(penguin), move(dog), move(rock))

Output:

flies walks stays

Un figlio sovrascrive un metodo del genitore definendone uno proprio. La sovrascrittura riguarda solo il figlio e tutto ciò che si trova al di sotto di esso; il genitore e gli altri suoi figli mantengono il metodo del genitore:

move <- function(x) UseMethod("move")
move.animal <- function(x) "walks"
move.bird <- function(x) "flies"
move.penguin <- function(x) "swims"
penguin <- structure(list(), class = c("penguin", "bird", "animal"))
sparrow <- structure(list(), class = c("bird", "animal"))
cat(move(penguin), move(sparrow))

Output:

swims flies

Ogni generico viene cercato per conto proprio. Un oggetto può usare sound() dalla propria classe e move() da una classe genitore, e un metodo genitore può chiamare altri generici che eseguono nuovamente il dispatch sulla classe figlia:

sound <- function(x) UseMethod("sound")
move <- function(x) UseMethod("move")
describe <- function(x) UseMethod("describe")
sound.animal <- function(x) "..."
sound.dog <- function(x) "woof"
move.animal <- function(x) "walks"
describe.animal <- function(x) paste(x$name, "says", sound(x), "and", move(x))
rex <- structure(list(name = "Rex"), class = c("dog", "animal"))
print(describe(rex))

Risultato:

[1] "Rex says woof and walks"

Per un oggetto con un attributo class, il dispatch considera solo quell’attributo e poi il metodo predefinito. L’oggetto al suo interno è ancora una lista, ma non viene provato un metodo per list:

size <- function(x) UseMethod("size")
size.list <- function(x) "a list"
size.default <- function(x) "default"
bag <- structure(list(1, 2), class = "bag")
cat(size(list(1, 2)), "/", size(bag))

Output:

a list / default
challenge icon

Sfida

Facile

Un quadrato è un rettangolo con i lati uguali. In Rectangle.R scrivi i metodi area.rectangle(), perimeter.rectangle() e name.rectangle(), che restituisce rectangle 2x3. In Square.R completa new_square(side), che chiama new_rectangle() con la classe square, e sovrascrivi solo name() con name.square(), che restituisce square 2. I quadrati devono usare area() e perimeter() del rettangolo.

I generici e new_rectangle() sono forniti. Il codice fornito legge righe con due numeri (un rettangolo) o uno (un quadrato) e stampa square 2: area 4, perimeter 8.

Il tuo codice va inserito in Rectangle.R e Square.R. main.R contiene il codice fornito per l'input/output e non può essere modificato.

Provalo tu

source("Rectangle.R")
source("Square.R")

# Codice di input/output fornito: lascialo così com'è
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  n <- as.numeric(strsplit(line, " ")[[1]])
  s <- if (length(n) == 1) new_square(n[1]) else new_rectangle(n[1], n[2])
  cat(name(s), ": area ", area(s), ", perimeter ", perimeter(s), "\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