Menu
Coddy logo textTech

Kolejność wyszukiwania metod

Część sekcji Programowanie obiektowe ścieżki R w Coddy. Lekcja 13 z 57.

Przy każdym wywołaniu R przechodzi przez wektor klas od lewej do prawej i uruchamia pierwszą znalezioną metodę. Jeśli żadna klasa nie ma metody, używa metody domyślnej. Różne obiekty w jednej hierarchii mogą zatrzymać się na różnych poziomach:

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

Wynik:

flies walks stays

Klasa potomna przesłania metodę klasy nadrzędnej, definiując własną. Przesłonięcie dotyczy tylko klasy potomnej i wszystkiego, co znajduje się poniżej niej; klasa nadrzędna i jej pozostałe klasy potomne zachowują metodę klasy nadrzędnej:

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

Wynik:

swims flies

Każda funkcja generyczna jest wyszukiwana osobno. Jeden obiekt może korzystać z sound() z własnej klasy i z move() z klasy nadrzędnej, a metoda klasy nadrzędnej może wywoływać inne funkcje generyczne, które ponownie wybierają metodę na podstawie klasy potomnej:

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

Wynik:

[1] "Rex says woof and walks"

W przypadku obiektu z atrybutem klasy wyszukiwanie metody uwzględnia tylko ten atrybut, a następnie metodę domyślną. Wewnątrz obiekt nadal jest listą, ale metoda dla list nie jest sprawdzana:

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

Wynik:

a list / default
challenge icon

Wyzwanie

Łatwy

Kwadrat to prostokąt o równych bokach. W pliku Rectangle.R napisz metody area.rectangle(), perimeter.rectangle() i name.rectangle(), która zwraca rectangle 2x3. W pliku Square.R uzupełnij new_square(side), która wywołuje new_rectangle() z klasą square, i zastąp tylko name() metodą name.square(), która zwraca square 2. Kwadraty muszą korzystać z metod area() i perimeter() prostokąta.

Funkcje generyczne i new_rectangle() są podane. Dostarczony kod odczytuje wiersze zawierające dwie liczby (prostokąt) lub jedną (kwadrat) i wypisuje square 2: area 4, perimeter 8.

Twój kod umieść w plikach Rectangle.R i Square.R. Plik main.R zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

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

# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator R online