2

I am using R6 to build an object which fields includes a data frame and other informations.
I defined a first method $print() which I can call as obj1$print() or print(obj1) and both ways works just fine.

> obj1$print()
test object name: AA
> print(obj1)
test object name: AA

I defined a second method $summary(), which is a generic function same as $print(): in this case the call obj1$summary() works as expected:

> obj1$summary()
test object name: AA
     alpha               beta  
 Min.   :-1.63751   a      :1  
 1st Qu.:-0.38065   b      :1  
 Median :-0.05854   c      :1  
 Mean   :-0.01360   d      :1  
 3rd Qu.: 0.46194   e      :1  
 Max.   : 1.34755   f      :1  
                    (Other):4 

but summary(obj1) returns an error:

Error in object[[i]] : wrong arguments for subsetting an environment

The example code is as follows:

testobj <- R6::R6Class(classname = "testobj",
                       public = list(
                         name = NULL,
                         data = NULL,
                         initialize = function(name, data) {
                           self$name <- name
                           self$data <- data
                         },
                         print = function(...) {
                           cat("test object name: ", self$name, "\n", sep = "")
                           invisible(self)
                         },
                         summary = function() {
                           cat("test object name: ", self$name, "\n", sep = "")
                           summary(self$data)
                           }
                         )
                       )

obj1 <- testobj$new(name = "AA",
                   data = data.frame(alpha = rnorm(10),
                                     beta = letters[1:10]))

My understanding is that within an object you can define methods with the same name as generic functions and those methods are dispatched automatically to the function based on the class of the object, as it happens to $print(). Isn't that correct?
Why the same approach does not works with $summary()? How can I fix that?

Many thanks for the help.

frenkg
  • 23
  • 4

1 Answers1

2

S3 methods, which is what you're looking for are different than R6 methods. For one thing, they aren't part of the object.

Make an S3 method for your class:

summary.testobj <- function(obj) {
    obj$summary()
}

summary(obj1)
SmokeyShakers
  • 3,372
  • 1
  • 7
  • 18
  • Thanks @SmokeyShakers. Just to make sure I understand you: 1. `$print()` is defined as both S3 and R6 method, and `$summary()` is defined just as S3 method. 2. You mean to rewrite the whole class as an S3 object, or to include an S3 method within the R6 object? Is that possible? – frenkg Jan 07 '20 at 22:01
  • So you can see that R6 has it's own default S3 print here `R6:::print.r6`. It doesn't have a `summary` method though. I wouldn't rewrite anything if i was you. I think S3 and R6 can work in tandem well. Your `summary.testobj` proves that. – SmokeyShakers Jan 08 '20 at 00:39
  • Thanks, it’s clear now, I got the logic behind – frenkg Jan 08 '20 at 02:45
  • This doesn't seem to work as of 2023 , especially if you try to put this in a package. – Pedro Lima Jan 13 '23 at 03:53
  • What do you mean? There's [specific export rules for S3 methods for packages](https://stackoverflow.com/questions/18512528/how-to-export-s3-method-so-it-is-available-in-namespace). Is that what you're referring to? – SmokeyShakers Jan 17 '23 at 20:06