Ron Jensen
Ron Jensen

Reputation: 652

Passing Method as a Character String

I need to allow the user to create an object with one of several classes. The object will require further analysis so will be passed to one of numerous S3 methods downstream.

My thought is to have them provide the class as a character string on the creation function call, but I'm not sure the best way to use useMethod to select the proper S3 method, since the different objects will be created with different algorithms.

The create_thing() function will return an object with class set, so graph_thing() and report_thing() will take the output of create_thing() and have a class to work with.

create_thing <- function(model = 'strange', foo, bar){
  tmp <- ""
  class(tmp)<-model
  UseMethod("create_thing", tmp)
}

create_thing.strange <- function(model, foo = 1, bar = 2){
  ## stuff
  print("strange")
  return(structure(list(data=runif(5)), class = c("list", "strange")))
}

create_thing.normal <- function(model, foo = 3, bar = 4){
  ## stuff
  print("normal")
  return(structure(list(data=rnorm(5)), class = c("list", "normal")))
}

graph_thing <- function(athing){
  UseMethod("graph_thing")
}

graph_thing.normal <- function(athing){
  print("normal")
  plot(athing$data)
}

graph_thing.strange <- function(athing){
  print("strange")
  plot(athing$data)
}

report_thing <- function(athing){
  UseMethod("report_thing")
}

report_thing.normal <- function(athing){
  print("normal")
  print(mean(athing$data))
}

report_thing.strange <- function(athing){
  print("strange")
  print(median(athing$data))
}

Upvotes: 1

Views: 81

Answers (1)

MrFlick
MrFlick

Reputation: 206232

The UseMethod function looks up the call stack to see what was passed in to the original function. Any modifications or new objects created will not influence how dispatching works.

If you are using the create_thing functions to initilize the object, then you should create a separate generic function for that

create_thing <- function(model = 'strange', foo, bar){
  tmp <- ""
  class(tmp)<-model
  init_thing(tmp, foo, bar)
}

init_thing <- function(model, foo=0, bar=0) {
    UseMethod("init_thing")
}
init_thing.strange <- function(model, foo = 1, bar = 2){
  ## stuff
  print("strange")
  return(structure(list(data=runif(5)), class = c("list", "strange")))
}

init_thing.normal <- function(model, foo = 3, bar = 4){
  ## stuff
  print("normal")
  return(structure(list(data=rnorm(5)), class = c("list", "normal")))
}

Upvotes: 1

Related Questions