Menu
Coddy logo textTech

Ordem de busca de métodos

Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 13 de 57.

Para cada chamada, R percorre o vetor de classes da esquerda para a direita e executa o primeiro método que encontra. Se nenhuma classe tiver um método, ele usa o padrão. Objetos diferentes em uma mesma hierarquia podem parar em níveis diferentes:

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

Saída:

flies walks stays

Uma classe filha substitui um método da classe pai definindo o seu próprio. A substituição afeta apenas a classe filha e tudo que estiver abaixo dela; a classe pai e suas outras classes filhas mantêm o método da classe pai:

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

Saída:

swims flies

Cada genérico é consultado por conta própria. Um objeto pode obter sound() de sua própria classe e move() de uma classe pai, e um método da classe pai pode chamar outros genéricos que fazem o despacho novamente na classe filha:

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

Saída:

[1] "Rex says woof and walks"

Para um objeto com um atributo de classe, o despacho considera apenas esse atributo e, em seguida, o padrão. Internamente, o objeto ainda é uma lista, mas um método para list não é tentado:

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

Saída:

a list / default
challenge icon

Desafio

Fácil

Um quadrado é um retângulo com lados iguais. Em Rectangle.R, escreva os métodos area.rectangle(), perimeter.rectangle() e name.rectangle(), que retorna rectangle 2x3. Em Square.R, complete new_square(side), que chama new_rectangle() com a classe square, e substitua apenas name() por name.square(), que retorna square 2. Os quadrados devem usar a area() e o perimeter() do retângulo.

Os genéricos e new_rectangle() são fornecidos. O código fornecido lê linhas com dois números (um retângulo) ou um (um quadrado) e imprime square 2: area 4, perimeter 8.

Seu código deve ser colocado em Rectangle.R e Square.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

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

# Código de entrada/saída fornecido: mantenha-o como está
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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de R online