Skip to content
Prev 327067 / 398503 Next

'save' method for S4 class

On 07/18/2013 03:47 AM, Simon Zehnder wrote:
The implementation offered by Christofer shows write.table, and the end result 
is a text file rather than a binary file expected from base::save. This makes it 
seem inappropriate to use 'save' in this context.

Instead, it seems that what Cristofer wants to implement is functionality to 
support write.table. ?write.table says

      'write.table' prints its required argument 'x' (after converting
      it to a data frame if it is not one nor a matrix)

So implementing an S3 method

   as.data.frame.MyClass <-
       function(x, row.names=NULL, optional=FALSE, ...)
   {
       x at x
   }

is all that is needed, gaining lots of flexibility by re-using the code of 
write.table.

   myClass = new("MyClass", x=data.frame(x=1:3, y=3:1))
   write.table(myClass, stdout())

In the case of a 'save' method producing binary output (but this is what save 
does already...), I think it's better practice to promote the non-generic 'save' 
to an S4 generic using it's existing arguments; in this case it makes sense to 
restrict dispatch to '...', so

   setGeneric("save", signature="...")

The resulting generic is

 > getGeneric("save")
standardGeneric for "save" defined from package ".GlobalEnv"

function (..., list = character(), file = stop("'file' must be specified"),
     ascii = FALSE, version = NULL, envir = parent.frame(), compress = !ascii,
     compression_level, eval.promises = TRUE, precheck = TRUE)
standardGeneric("save")
<environment: 0x4a7b860>
Methods may be defined for arguments: ...
Use  showMethods("save")  for currently available ones.

This means that a method might be defined as

   setMethod("save", "MyClass", function(..., list = character(),
       file = stop("'file' must be specified"), ascii = FALSE, version = NULL,
       envir = parent.frame(), compress = !ascii, compression_level,
       eval.promises = TRUE, precheck = TRUE)
   {
       ## check non-sensical or unsupported user input for 'MyClass'
       if (!is.null(version))
           stop("non-NULL 'version' not supported for 'MyClass'")
       ## ...
       ## implement save on MyClass
   })

It might be that Christofer wants to implement a 'write.table-like' (text 
output) or a 'save-like' (binary output) function that really does not conform 
to the behavior of write.table (e.g., producing output that could not be input 
by read.table) or save. Then I think the better approach is to implement 
writeMyClass (for text output) or saveMyClass (for binary output).

Martin