R Anleitungen

Generische Funktionen

Eine generische Funktion ist eine Funktion, die auf verschiedene Typen von Variablen angewandt werden kann und je nach Typ der Variablen unterschiedliche Ergebnisse liefert.

Generische Funktionen sind Teil der Art und Weise, wie R Objektorientierte Programmierung implementiert. Der Kern eines jeden objektorientierten Systems sind die Konzepte von Klasse und Methode.

Eine Klasse definiert einen Objekttyp und beschreibt, welche Eigenschaften er besitzt, wie er sich verhält und wie er sich zu anderen Objekttypen verhält. Jedes Objekt muss eine Instanz einer Klasse sein. Eine Methode ist eine Funktion, die mit einem bestimmten Objekttyp zugeordnet ist.

R verwendet eine Art der objektorientierten Programmierung, die generische Funktion Objektorientierung genannt wird. Dies unterscheidet sich von vielen anderen Programmiersprachen, wie Java, C++ und C#, die Nachrichtenaustausch (message-passing object-oriented programming) implementieren. Beim Nachrichtenaustausch werden Nachrichten (Methoden) an Objekte gesendet und das Objekt bestimmt, welche Funktion aufgerufen werden soll. Bei solchen Programmiersprachen werden die Typen der Parameter bei der Definition angegeben werden (function overloading), während der Name der Funktion stets gleich bleibt.

R ist anders, aber doch sehr ähnlich. In R wird der Typ des Objekts getrennt von einem Punkt nach dem eigentlich Funktionsnamen geschrieben. Dieses Verhalten kann man sehr gut anhand der Funktion summary sehen.

summary fasst die Ausgabe verschiedener Objekte zusammen. Allerdings muss dich die Funktion gleichzeitig dem Objekt anpassen, dass es zusammenfassen soll. Eine ANOVA muss anders zusammengefasst werden, als beispielsweise ein Zahlenvektor. Dennoch akzeptiert summary problemlos beide Variablentypen und produziert eine sinnvolle und relevante Ausgabe. Ursächlich für dieses Verhalten sind generische Funktionen, die jeweils für beide Typen von Variablen existieren. Die Funktion zum Zusammenfassen von AOV-Objekten heißt entsprechend summary.aov.

Statt vieler einzelner summary-Funktionen (jeweils eine für ein Objekt), könnte man auch eine einzelne Funktion schreiben, die entsprechend über if...else und typeof bzw. class den Typ zu ermitteln und dann die entsprechende sinnvolle Zusammenfassend zu produzieren. Dieser Ansatz hat allerdings verschiedene Nachteile, unter anderem die Lesbarkeit und Pflegbarkeit des Codes, die mangelhafte Einhalten von objektorientierten Programmierkonzepten und fehlende Erweiterbarkeit durch Pakete.

Die ersten beiden Punkte sind vor allem aus der Sicht der Programmierer wichtig, die R schreiben und mögen für den Endanwender erst einmal nur bedingt von Relevanz sein – der letzte Punkt allerdings schon. Dank des Konzepts der generischen Funktionen können wir eine Standardfunktion wie summary, plot oder print definieren, die immer eine gewünschte Aufgabe erfüllt und von Autoren neuer Pakete jeweils für eigene Klassen definiert werden kann. So fasst die Funktion summary.zlm aus dem Paket MAST eine Variable des Typs zlm zusammen, das vorher durch dasselbe Paket definiert und berechnet wurde. Hätten wir keine generischen Funktionen, müssten wir immer die summary-Funktion neu definieren.

Generell haben generische Funktionen folgende Vorteile:

  • Sie liefern ein sinnvolles Ergebnis basierend auf dem Typ des Eingabeobjekts
  • Sie tragen zur Standardisierung bei
  • Sie erleichtern das Schreiben von übersichtlichem Code
  • Sie verdecken die interne Komplexität gegenüber dem Benutzer
  • Sie ermöglichen die Ausweitung bestehender Funktionen auf neue Objekte