Object Oriented Programming in R

[This article was first published on Jason Bryer » R, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

As someone who was a Java programmer for many years learning R’s object oriented programming framework has been frustrating to say the least. I like the simplicity of S3 but find it limiting when you wish to write methods that change the underlying data elements. That is, printing, summarizing, and plotting work great because they generally do not require changes to the data in the class passed to it. After much experimenting it occurred to me that perhaps I could achieve a more Java like behavior by adding functions to the class. For simple things this works great. To make it even more flexible I found that if you change the list to an environment before assigning the class allows one to change lists within the list.

The following example models the framework for an email class (without actually doing anything useful). That is, I want a class that contains an email address and name and the ability to send email. I would also like to save a history of the emails sent. As can be seen, functions that work with atomic variables are pretty straight forward. Working with lists require (well maybe required, if you know of a better way leave a comment) using the assign function. This may not produce the cleanest source code but (IMHO) provides a better experience for the user.

#' ConstructorEmailClass <- 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 functions	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=''))}
if(FALSE) {  #Test code that won't be run when sourcing this file	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]')}
view raw EmailClass.R This Gist brought to you by GitHub.

To leave a comment for the author, please follow the link and comment on their blog: Jason Bryer » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)