Menu
Coddy logo textTech

Generics erstellen

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

Ein S4-Generic wird mit setGeneric() erstellt. Sein Funktionskörper ist standardGeneric("name"), das S4-Gegenstück zu UseMethod(). setGeneric() gibt den Namen des Generics zurück, der ausgegeben wird, wenn es auf der obersten Ebene aufgerufen wird:

setGeneric("area", function(shape) standardGeneric("area"))

Ausgabe:

[1] "area"

Umschließe den Aufruf mit invisible(), damit diese Zeile nicht in der Ausgabe erscheint. setMethod("area", "Circle", ...) fügt dann die Methode für eine Klasse hinzu:

setClass("Circle", slots = c(r = "numeric"))
setClass("Square", slots = c(side = "numeric"))
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
setMethod("area", "Square", function(shape) shape@side^2)
cat(area(new("Circle", r = 1)), area(new("Square", side = 3)))

Ausgabe:

3.141593 9

Eine Methode hat dieselben Argumente wie ihre generische Funktion. Wenn die generische Funktion ... enthält, kann eine Methode danach eigene benannte Argumente hinzufügen:

setClass("Circle", slots = c(r = "numeric"))
invisible(setGeneric("describe", function(x, ...) standardGeneric("describe")))
setMethod("describe", "Circle", function(x, ..., digits = 2) {
  paste("circle of area", round(pi * x@r^2, digits))
})
c1 <- new("Circle", r = 2)
print(describe(c1))
print(describe(c1, digits = 4))

Ausgabe:

[1] "circle of area 12.57"
[1] "circle of area 12.5664"

setMethod() benötigt das Generikum bereits, daher wird die Datei mit setGeneric() zuerst eingebunden. Ein Aufruf für eine Klasse ohne Methode bricht mit einem Fehler ab, der die Signatur nennt:

invisible(setGeneric("area", function(shape) standardGeneric("area")))
setClass("Circle", slots = c(r = "numeric"))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
area(42)

Ausgabe:

Error: unable to find an inherited method for function ‘area’ for signature ‘shape = "numeric"’
Execution halted
challenge icon

Aufgabe

Einfach

Shapes sind S4-Klassen in drei Dateien. Erstelle in Shape.R die Generics area(shape) und perimeter(shape) mit setGeneric(), eingeschlossen in invisible(). In Circle.R und Square.R werden die Klassen deklariert; füge für jede Klasse die Methoden area und perimeter mit setMethod() hinzu.

Der bereitgestellte Code liest Zeilen wie circle 2 oder square 3 und gibt circle: area 12.57, perimeter 12.57 aus.

Dein Code gehört in Shape.R, Circle.R und Square.R. main.R enthält den bereitgestellten Ein-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

source("Shape.R")
source("Circle.R")
source("Square.R")

# Bereitgestellter Ein-/Ausgabe-Code: belasse ihn unverändert
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  s <- if (p[1] == "circle") new("Circle", r = as.numeric(p[2])) else new("Square", side = as.numeric(p[2]))
  cat(sprintf("%s: area %.2f, perimeter %.2f", p[1], area(s), 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