Search code examples
rr-s4

How to access a S4 object's method


My current project is using S4 objects and I would like to access the generic methods like in python or C. Here is the example

setClass("Account",
         representation(balance = 'numeric', holder = 'character'),
         prototype = prototype(balance = NA_real_, holder = NA_character_),
         validity = function(object) {
           if (object@balance < 10) {
             return("The start balance should not be negative")
           }
           return(TRUE)
         })

setMethod("show", signature = "Account",
          definition = function(object) {
            cat("The account holder is", object@holder, "\n")
            cat("The account balance is", object@balance, "\n")
          })

setGeneric("deposit", def = function(.Object, amount) {
  standardGeneric("deposit")
})

setMethod("deposit", signature = "Account",
          definition = function(.Object, amount) {
            nameObject <- deparse(substitute(.Object))
            .Object@balance <- .Object@balance + amount
            assign(nameObject, .Object, envir = parent.frame())
            return(invisible())
      })

Currently I can use the following:

acc <- new("Account", balance = 10, holder = "nal-ra")
deposit(acc, 20)
acc
#> The account holder is nal-ra 
#> The account balance is 30 

I would like use the acc$.$deposit(20) instead of deposit(acc, 20).

I know that reference class and R6 class can do the job, but my project can not use them.


Solution

  • S4 methods don't work that way. Instead, update and return the object

    setMethod("deposit", signature = "Account",
        definition = function(.Object, amount) {
            .Object@balance <- .Object@balance + amount
            .Object
    })
    
    acc = deposit(acc, 20)
    

    A different formulation would be to write a deposit<- replacement method

    setGeneric("deposit<-", function(x, value) standardGeneric("deposit<-"))
    setReplaceMethod("deposit", c("Account", "numeric"), function(x, value) {
        x@balance <- x@balance + value
        x
    })
    

    with

    > acc <- new("Account", balance = 10, holder = "nal-ra")
    > deposit(acc) <- 20
    > acc
    The account holder is nal-ra 
    The account balance is 30