Search code examples
roopr-s4

S4: Use class attributes as default input values for class methods


I'm new to S4 OO system in R. I'm thinking to use class attributes as default input into generic methods, but I got an error message saying that argument "xxx" is missing, with no default.

Basically I have a list of functions (i.e. class methods) which operate at the same set of class attributes. I wish to use these class attributes as the default input values to the list of functions, but the way I implemented (I used definition = function(theObject, input = theObject@attribute1), see example code below) throws error... Why it's not working?

Many thanks in advance!

class1 = setClass("class1", 
                  slots = c(attribute1 = "numeric"), 
                  prototype = list(
                    attribute1 = NULL
                  ))

setGeneric(name = "method1", 
           def = function(theObject, input){
             standardGeneric("method1")
           })

setMethod(f = "method1", 
          signature = "class1", 
          definition = function(theObject, input = theObject@attribute1){
            theObject@attribute1 = input + 1
            return (theObject)
          })


x = class1() # instantiate an object from class1
x@attribute1 = 1 # set attribute value
method1(x, input = 2) # This works fine if I use "input = 2" explicitly

# This throws the following error "Error in method1(x) : argument "input" is missing, with no default"
# Even though in setMethod part I did specify the default value of input
method1(x)

Solution

  • Not sure why this is the case, but in order to set a default for an input with setMethod, the generic requires a default as well. e.g.:

    class1 = setClass("class1", 
                      slots = c(attribute1 = "numeric"), 
                      prototype = list(
                        attribute1 = NULL
                      ))
    
    setGeneric(name = "method1", 
               def = function(theObject, input=NA){ #Setting any input here enables defaults for methods
                 standardGeneric("method1")
               })
    
    setMethod(f = "method1", 
              signature = "class1", 
              definition = function(theObject, input=1){
                theObject@attribute1 = input + 1
                return (theObject)
              })
    
    x = class1() 
    x@attribute1 = 1 
    method1(x, input = 2) 
    method1(x)