0

Here is an example from the official help page:

## a simple editor for matrix objects.  Method  $edit() changes some
## range of values; method $undo() undoes the last edit.
mEdit <- setRefClass("mEdit",
                     fields = list( data = "matrix",
                                    edits = "list"),
                     methods = list(
                         edit = function(i, j, value) {
                             ## the following string documents the edit method
                             'Replaces the range [i, j] of the
                             object by value.
                             '
                             backup <-
                                 list(i, j, data[i,j])
                             data[i,j] <<- value
                             edits <<- c(edits, list(backup))
                             invisible(value)
                         },
                         undo = function() {
                             'Undoes the last edit() operation
        and update the edits field accordingly.
        '
                             prev <- edits
                             if(length(prev)) prev <- prev[[length(prev)]]
                             else stop("No more edits to undo")
                             edit(prev[[1]], prev[[2]], prev[[3]])
                             ## trim the edits list
                             length(edits) <<- length(edits) - 2
                             invisible(prev)
                         },
                         show = function() {
                             'Method for automatically printing matrix editors'
                             cat("Reference matrix editor object of class",
                                 classLabel(class(.self)), "\n")
                             cat("Data: \n")
                             methods::show(data)
                             cat("Undo list is of length", length(edits), "\n")
                         }
                     ))


mEdit$methods(
    save = function(file) {
        'Save the current object on the file
        in R external object format.
       '
        base::save(.self, file = file)
    }
)



mv <- setRefClass("matrixViewer",
                  fields = c("viewerDevice", "viewerFile"),
                  contains = "mEdit",
                  methods = list( view = function() {
                      dd <- dev.cur(); dev.set(viewerDevice)
                      devAskNewPage(FALSE)
                      matplot(data, main = paste("After",length(edits),"edits"))
                      dev.set(dd)},
                      edit = # invoke previous method, then replot
                          function(i, j, value) {
                              callSuper(i, j, value)
                              view()
                          }))

## initialize and finalize methods
mv$methods( initialize =
                function(file = "./matrixView.pdf", ...) {
                    viewerFile <<- file
                    pdf(viewerFile)
                    viewerDevice <<- dev.cur()
                    dev.set(dev.prev())
                    callSuper(...)
                },
            finalize = function() {
                dev.off(viewerDevice)
            })

Everything works as advertised, but if I add something like this:

mEdit$methods(
    initialize = function(data) {
        data <<- data
    }
)

Then try load the class, R complains:

Loading testRefClass
Error in .Object$initialize(...) (from testRefClass.R#52) : 
  argument "data" is missing, with no default

Isn't data in the ... arg? Why is R saying it's missing?

qed
  • 22,298
  • 21
  • 125
  • 196
  • Give it a default `initialize = function(data = matrix())` – jdharrison Aug 14 '14 at 21:00
  • 1
    Thanks. Just checked the doc: `Therefore, your method should normally include ... as an argument, all other arguments should have defaults or check for missingness, and your method should pass all initialized values on via $callSuper() or $initFields() if you know that your superclasses have no initialization methods.` – qed Aug 14 '14 at 21:03
  • Could you post an answer and expound on this? I am not sure about what the doc means here. – qed Aug 14 '14 at 21:05

1 Answers1

0

You can give the parameters passed in the initialize method default values:

mEdit$methods(
  initialize = function(data = matrix()) {
    data <<- data
  }
)

 nn <- mEdit()
> nn
Reference matrix editor object of class "mEdit" 
Data: 
     [,1]
[1,]   NA
Undo list is of length 0 

> nn <- mEdit(data = matrix(1:4, 2,2))
> nn
Reference matrix editor object of class "mEdit" 
Data: 
     [,1] [,2]
[1,]    1    3
[2,]    2    4
Undo list is of length 0 

That should take care of the error message.

mv inherits from mEdit therefore callSuper(...) should be called in its initialize method:

> rr <- mv()
> rr
Reference matrix editor object of class "matrixViewer" 
Data: 
     [,1]
[1,]   NA
Undo list is of length 0 

and we can see that instantiating a new mv leads to the initialize method from mEdit being called via the callSuper(...).

> rr <- mv(data = matrix(1:4, 2,2))
> rr
Reference matrix editor object of class "matrixViewer" 
Data: 
     [,1] [,2]
[1,]    1    3
[2,]    2    4
Undo list is of length 0 

so inheritance is working as expected.

jdharrison
  • 30,085
  • 4
  • 77
  • 89
  • 1
    According to the help page, I should add `...` even to mEdit$initialize(), and call initFields(...) in it? – qed Aug 14 '14 at 21:19