# Object-Oriented Programming in R: The Setter Methods

December 14, 2009
By

(This article was first published on John Myles White: Die Sudelbücher » Statistics, and kindly contributed to R-bloggers)

With a little guidance from the indefatigable Hadley Wickham, I figured out today how to implement the setter methods that were missing from my example user class. To review, let’s rebuild the getter methods for my user object:

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35  user <- list(id = 1, password = '286755fad04869ca523320acce0dc6a4', email = '[email protected] /* */')   class(user) <- 'user'   id <- function(x) { UseMethod('id', x) }   id.user <- function(user) { return(user[['id']]) }   password <- function(x) { UseMethod('password', x) }   password.user <- function(user) { return(user[['password']]) }   email <- function(x) { UseMethod('email', x) }   email.user <- function(user) { return(user[['email']]) }

With these working, my goal was to write setter methods that would work like the ideal code below:

 1 2 3 4 5 6  id(user) <- 2   if (id(user) == 2) { print("Succeeded in editing the user's id attribute.") }

Defining this sort of setter method turned out to require a little effort. I wasted quite a lot of time walking down dead ends, but, thankfully, Hadley gave me the exact piece of information I was missing early this morning. The dead ends were interesting in themselves, though, so I’ll review them in another post tomorrow.

For now I’ll just explain the correct implementation for my desired setter methods, which you can see below:

 1 2 3 4 5 6 7 8 9 10  'id<-' <- function(x, value) { UseMethod('id<-', x) }   'id<-.user' <- function(x, value) { x[['id']] <- value return(x) }

There are three important ideas here:

1. The generic setter method for id should be called 'id<-', which must always be quoted to prevent parsing errors.
2. The class level setter method should be called 'id<-.user', which isn't surprising, though I had imagined it might be called 'id.user<-' at one point.
3. The setter method should make a change to a copy of the original object and return the edited copy to the caller. R handles the assignment of this edited return value to the original object behind the scenes. In fact, not using this return value approach will make otherwise plausible looking code fail to edit your object correctly. I stumbled on that for quite a while before I was shown the light.

With this in mind, a final user class looks like this:

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68  user <- list(id = 1, password = '286755fad04869ca523320acce0dc6a4', email = '[email protected] /* */')   class(user) <- 'user'   id <- function(x) { UseMethod('id', x) }   id.user <- function(user) { return(user[['id']]) }   password <- function(x) { UseMethod('password', x) }   password.user <- function(user) { return(user[['password']]) }   email <- function(x) { UseMethod('email', x) }   email.user <- function(user) { return(user[['email']]) }   'id<-' <- function(x, value) { UseMethod('id<-', x) }   'id<-.user' <- function(x, value) { x[['id']] <- value return(x) }   'password<-' <- function(x, value) { UseMethod('password<-', x) }   'password<-.user' <- function(x, value) { x[['password']] <- value return(x) }   'email<-' <- function(x, value) { UseMethod('email<-', x) }   'email<-.user' <- function(x, value) { x[['email']] <- value return(x) }

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...