Menu
CoddyTech

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, dass das Generikum bereits existiert. Daher wird zuerst die Datei mit setGeneric() geladen. Ein Aufruf für eine Klasse ohne Methode wird mit einem Fehler abgebrochen, 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

Formen sind S4-Klassen in drei Dateien. Erstelle in Shape.R die Generika area(shape) und perimeter(shape) mit setGeneric(), umschlossen von 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 ein 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 kann nicht bearbeitet werden.

Probier es selbst

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

# Vorgegebener Ein-/Ausgabecode: unverändert lassen
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