Menu
Coddy logo textTech

Reihenfolge der Methodensuche

Teil des Abschnitts Objektorientierte Programmierung der R-Journey von Coddy. Lektion 13 von 57.

Bei jedem Aufruf durchläuft R den Klassenvektor von links nach rechts und führt die erste Methode aus, die es findet. Wenn keine Klasse eine Methode besitzt, verwendet R die Standardmethode. Verschiedene Objekte innerhalb einer Hierarchie können auf unterschiedlichen Ebenen anhalten:

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

Ausgabe:

flies walks stays

Ein untergeordnetes Objekt überschreibt eine Methode des übergeordneten Objekts, indem es eine eigene definiert. Die Überschreibung wirkt sich nur auf das untergeordnete Objekt und alles darunter aus; das übergeordnete Objekt und seine anderen untergeordneten Objekte behalten die Methode des übergeordneten Objekts bei:

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

Ausgabe:

swims flies

Jedes Generic wird für sich selbst nachgeschlagen. Ein Objekt kann sound() aus seiner eigenen Klasse und move() von einem übergeordneten Objekt übernehmen, und eine Methode des übergeordneten Objekts kann andere Generics aufrufen, die erneut auf das untergeordnete Objekt dispatchen:

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

Ausgabe:

[1] "Rex says woof and walks"

Bei einem Objekt mit einem Klassenattribut berücksichtigt die Dispatch-Logik nur dieses Attribut und anschließend die Standardmethode. Das Objekt ist intern weiterhin eine Liste, aber eine Methode für list wird nicht ausprobiert:

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

Ausgabe:

a list / default
challenge icon

Aufgabe

Einfach

Ein Quadrat ist ein Rechteck mit gleich langen Seiten. Schreibe in Rectangle.R die Methoden area.rectangle(), perimeter.rectangle() und name.rectangle(), die rectangle 2x3 zurückgibt. Vervollständige in Square.R new_square(side), das new_rectangle() mit der Klasse square aufruft, und überschreibe nur name() mit name.square(), das square 2 zurückgibt. Quadrate müssen die area() und perimeter() des Rechtecks verwenden.

Die Generics und new_rectangle() sind vorgegeben. Der bereitgestellte Code liest Zeilen mit zwei Zahlen (ein Rechteck) oder einer Zahl (ein Quadrat) ein und gibt square 2: area 4, perimeter 8 aus.

Dein Code gehört in Rectangle.R und Square.R. main.R enthält den bereitgestellten Eingabe-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

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

# Bereitgestellter Ein-/Ausgabe-Code: belasse ihn wie er ist
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 dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-R-Compiler