Menu
CoddyTech

Klassenvektoren

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

Die S3-Vererbung ergibt sich aus dem Klassenvektor. Ein Objekt mit class = c("manager", "employee") ist ein Manager und auch ein Mitarbeiter. Wenn es für manager keine Methode für eine generische Funktion gibt, wird die Suche fortgesetzt und die Methode für employee 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

Den Klassenvektor von Hand in jedem Konstruktor zu schreiben, wiederholt die Angaben des Elternteils. Stattdessen nimmt der Elternkonstruktor ein Argument class entgegen und stellt 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 Elternkonstruktors sammelt die zusätzlichen Felder des Kinds, hier reports, und fügt sie nach den eigenen Feldern des Elternteils ein. Ein einfacher Angestellter 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 zuerst. Steht die Elternklasse an erster Stelle, greifen ihre Methoden 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 die zugehörige employee-Methode sind vorgegeben, sodass Manager eine Beschriftung erhalten, ohne eine eigene Methode zu haben. Der vorgegebene Code liest Zeilen wie employee Bo 40000 oder manager Ada 60000 4 und gibt den Klassenvektor, die Feldnamen und die Beschriftung aus.

Dein Code gehört in Employee.R und Manager.R. main.R enthält den vorgegebenen Ein-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

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

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