Objektorientierte Programmierung auf die eine oder andere Weise ist in R sehr gut möglich. Im Gegensatz zu beispielsweise Python gibt es jedoch viele Möglichkeiten, eine Objektorientierung zu erreichen:
- Das R.oo-Paket
- Klassen S3 und S4
- Referenzklassen
- das Proto-Paket
Meine Frage ist:
Welche Hauptunterschiede unterscheiden diese Arten der OO-Programmierung in R?
Im Idealfall dienen die Antworten hier als Referenz für R-Programmierer, die versuchen zu entscheiden, welche OO-Programmiermethoden ihren Anforderungen am besten entsprechen.
Als solches bitte ich um Details, die objektiv, erfahrungsbasiert und mit Fakten und Referenzen versehen sind. Bonuspunkte für die Klärung, wie diese Methoden den Standard-OO-Praktiken zugeordnet werden.
Antworten:
S3-Klassen
print
Aufrufeprint.lm
print.anova
usw. Und wenn nicht gefunden,print.default
S4 Klassen
Referenzklassen
Proto
R6 Klassen
quelle
library("fortunes"); fortune("strait")
Bearbeiten am 08.03.12: Die folgende Antwort antwortet auf einen Teil der ursprünglich gestellten Frage, der inzwischen entfernt wurde. Ich habe es unten kopiert, um den Kontext für meine Antwort bereitzustellen:
Mein Beitrag bezieht sich auf Ihre zweite Frage, wie die OO-Methoden von R auf Standard-OO-Methoden abgebildet werden. Wie ich in der Vergangenheit darüber nachgedacht habe, bin ich immer wieder zu zwei Passagen zurückgekehrt, eine von Friedrich Leisch und die andere von John Chambers. Beide artikulieren gut, warum OO-ähnliche Programmierung in R einen anderen Geschmack hat als in vielen anderen Sprachen.
Zunächst Friedrich Leisch aus "Erstellen von R-Paketen: Ein Tutorial" ( Warnung: PDF ):
Die andere Passage stammt aus John Chambers 'großartigem Buch "Software for Data Analysis" . ( Link zur zitierten Passage ):
quelle
S3 und S4 scheinen die offiziellen (dh eingebauten) Ansätze für die OO-Programmierung zu sein. Ich habe begonnen, eine Kombination von S3 mit Funktionen zu verwenden, die in die Konstruktorfunktion / -methode eingebettet sind. Mein Ziel war es, eine Syntax vom Typ object $ method () zu haben, damit ich halbprivate Felder habe. Ich sage halbprivat, weil es keine Möglichkeit gibt, sie wirklich zu verstecken (soweit ich weiß). Hier ist ein einfaches Beispiel, das eigentlich nichts tut:
#' Constructor EmailClass <- function(name, email) { nc = list( name = name, email = email, get = function(x) nc[[x]], set = function(x, value) nc[[x]] <<- value, props = list(), history = list(), getHistory = function() return(nc$history), getNumMessagesSent = function() return(length(nc$history)) ) #Add a few more methods nc$sendMail = function(to) { cat(paste("Sending mail to", to, 'from', nc$email)) h <- nc$history h[[(length(h)+1)]] <- list(to=to, timestamp=Sys.time()) assign('history', h, envir=nc) } nc$addProp = function(name, value) { p <- nc$props p[[name]] <- value assign('props', p, envir=nc) } nc <- list2env(nc) class(nc) <- "EmailClass" return(nc) } #' Define S3 generic method for the print function. print.EmailClass <- function(x) { if(class(x) != "EmailClass") stop(); cat(paste(x$get("name"), "'s email address is ", x$get("email"), sep='')) }
Und ein Testcode:
test <- EmailClass(name="Jason", "[email protected]") test$addProp('hello', 'world') test$props test class(test) str(test) test$get("name") test$get("email") test$set("name", "Heather") test$get("name") test test$sendMail("[email protected]") test$getHistory() test$sendMail("[email protected]") test$getNumMessagesSent() test2 <- EmailClass("Nobody", "[email protected]") test2 test2$props test2$getHistory() test2$sendMail('[email protected]')
Hier ist ein Link zu einem Blog-Beitrag, den ich über diesen Ansatz geschrieben habe: http://bryer.org/2012/object-oriented-programming-in-r Ich würde Kommentare, Kritik und Vorschläge zu diesem Ansatz begrüßen, da ich nicht überzeugt bin ich selbst, wenn dies der beste Ansatz ist. Für das Problem, das ich zu lösen versuchte, hat es jedoch großartig funktioniert. Insbesondere für das makeR-Paket ( http://jbryer.github.com/makeR ) wollte ich nicht, dass Benutzer Datenfelder direkt ändern, da ich sicherstellen musste, dass eine XML-Datei, die den Status meines Objekts darstellt, synchron bleibt. Dies funktionierte einwandfrei, solange die Benutzer die in der Dokumentation beschriebenen Regeln einhalten.
quelle