Menu
Coddy logo textTech

Klassenvektoren

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

Die S3-Vererbung stammt aus dem Klassenvektor. Ein Objekt mit class = c("manager", "employee") ist ein Manager und zugleich ein Angestellter. Wenn ein Generikum keine Methode für manager hat, wird die Methodenverteilung fortgesetzt und die employee-Methode verwendet:

pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
m <- structure(list(name = "Ada", salary = 60000), class = c("manager", "employee"))
print(class(m))
print(pay(m))

Ausgabe:

[1] "manager"  "employee"
[1] 5000

Das manuelle Schreiben des Klassenvektors in jedem Konstruktor wiederholt die Details des Elternteils. Stattdessen nimmt der Elternkonstruktor ein class-Argument entgegen und setzt es vor seine eigene Klasse, und der Kindkonstruktor ruft den Elternkonstruktor auf:

new_employee <- function(name, salary, ..., class = character()) {
  structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
new_manager <- function(name, salary, reports) {
  new_employee(name, salary, reports = reports, class = "manager")
}
m <- new_manager("Ada", 60000, 4)
print(class(m))
print(names(m))

Ausgabe:

[1] "manager"  "employee"
[1] "name"    "salary"  "reports"

Das ... des Konstruktors der übergeordneten Klasse übernimmt die zusätzlichen Felder des Kindes, hier reports, und platziert sie hinter den eigenen Feldern der übergeordneten Klasse. Ein einfacher Mitarbeiter hat überhaupt kein Feld reports:

new_employee <- function(name, salary, ..., class = character()) {
  structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
e <- new_employee("Bo", 40000)
print(class(e))
print(names(e))

Ausgabe:

[1] "employee"
[1] "name"   "salary"

Die Reihenfolge des Klassenvektors ist wichtig: Die spezifischste Klasse steht an erster Stelle. Wenn die Elternklasse an erster Stelle steht, setzen sich ihre Methoden durch, und die Methoden der Kindklasse werden nie verwendet:

title <- function(x) UseMethod("title")
title.employee <- function(x) "employee"
title.manager <- function(x) "manager"
right <- structure(list(), class = c("manager", "employee"))
wrong <- structure(list(), class = c("employee", "manager"))
print(title(right))
print(title(wrong))

Ausgabe:

[1] "manager"
[1] "employee"
challenge icon

Aufgabe

Einfach

Mitarbeiter und Manager sind auf zwei Dateien aufgeteilt. Vervollständige new_employee(name, salary, ..., class = character()) in Employee.R: Die Funktion gibt eine Liste mit name, salary und allen zusätzlichen Feldern aus ... sowie dem Klassenvektor c(class, "employee") zurück. Vervollständige anschließend new_manager(name, salary, reports) in Manager.R; diese Funktion ruft new_employee() mit dem zusätzlichen Feld reports und der Klasse manager auf.

label() und seine employee-Methode sind vorgegeben, sodass Manager ohne eigene Methode ein Label erhalten. Der bereitgestellte Code liest Zeilen wie employee Bo 40000 oder manager Ada 60000 4 ein und gibt den Klassenvektor, die Feldnamen und das Label aus.

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

Probier es selbst

source("Employee.R")
source("Manager.R")

# Gelieferter Ein-/Ausgabecode: belasse ihn wie er ist
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  x <- if (p[1] == "manager") new_manager(p[2], as.numeric(p[3]), as.numeric(p[4])) else new_employee(p[2], as.numeric(p[3]))
  cat("class: ", paste(class(x), collapse = ", "), "\n", sep = "")
  cat("fields: ", paste(names(x), collapse = ", "), "\n", sep = "")
  cat(label(x), "\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