title: How to write coercion methods
body: <p>I'm having a bunch of custom-made Reference Classes and would like to write coercion methods for some of them. It'd be nice if a function call would look like this:</p>
  
  <pre><code>objectCoerce(src=obj, to="list", ...)
  </code></pre>
  
  <p>where <code>...</code> is the crucial part as sometimes I want to pass additional stuff for certain coercions (see <code>do.deep = TRUE/FALSE</code> below.</p>
  
  <p>However, in order to do that, do I need to implement sort of a "transformer" that takes the <code>to</code> argument, tries to instantiate an empty object of the class specified by <code>to</code> and then calls the "regular" method dispatch? Or is there a better way?</p>
  
  <p>Below you'll find my current solution. It works, but I'm "loosing" the option to coerce to class <code>character"</code> as this class is used to process things to the regular dispatcher and a <code>to = "character</code> would result in infinite recursion. Plus, it's a lot of overhead.</p>
  
  <h2>EDIT 2011-12-02</h2>
  
  <p>Of course <code>setAs</code> would be the first address to check. But the function specified by arg <code>def</code> in <code>setAs</code> can only take one argument, and often that's too rigid for me. For example, I don't see how I could include the <code>do.deep = TRUE/FALSE</code> switch when using <code>setAs</code>.</p>
  
  <h2>Class Defs</h2>
  
  <pre><code>setRefClass(Class="MyVirtual")
  
  setRefClass(
      Class="A",
      contains="MyVirtual",
      fields=list(
          x="character"
      )
  )
  
  setRefClass(
      Class="B",
      contains="MyVirtual",
      fields=list(
          x.a="A",
          x.b="numeric",
          x.c="data.frame"
      )
  )
  
  setGeneric(
      name="objectCoerce",
      signature=c("src", "to"),
      def=function(src, to, ...){
          standardGeneric("objectCoerce")       
      }
  )
  </code></pre>
  
  <h2>Generic Method</h2>
  
  <pre><code>setGeneric(
      name="objectCoerce",
      signature=c("src", "to"),
      def=function(src, to, ...){
          standardGeneric("objectCoerce")       
      }
  )
  </code></pre>
  
  <h2>Intermediate Transformer</h2>
  
  <pre><code>setMethod(
      f="objectCoerce",
      signature=signature(src="ANY", to="character"),
      definition=function(src, to, do.deep=FALSE, ...){        
  
      # Transform 'to' to a dummy object of class 'to'
      to.0 &lt;- to
      # For standard R classes
      try.res &lt;- try(eval(substitute(
          to &lt;- CLASS(), 
          list(CLASS=as.name(to.0))
      )), silent=TRUE)
      # For S4 classes
      if(inherits(try.res, "try-error")){
          try.res &lt;- try(eval(substitute(
              to &lt;- new(CLASS), 
              list(CLASS=to.0)
          )), silent=TRUE)
          # For my classes. In order to get an 'hollow' object, some of them 
          # need to be instantiated by 'do.hollow=TRUE'
          if(inherits(try.res, "try-error")){
              try.res &lt;- try(eval(substitute(
                  to &lt;- new(CLASS, do.hollow=TRUE), 
                  list(CLASS=to.0)
              )), silent=TRUE)
              if(inherits(try.res, "try-error")){
                  stop(try.res)
              }
          }
      }
      # Pass transformed 'to' along so the standard method 
      # dispatcher can kick in.
      out &lt;- objectCoerce(src=src, to=to, do.deep=do.deep, ...)
      return(out)
      }
  )
  </code></pre>
  
  <h2>Coercion Method 'MyVirtual' to 'list'</h2>
  
  <pre><code>setMethod(
      f="objectCoerce",
      signature=signature(src="MyVirtual", to="list"),
      definition=function(src, to, do.deep=FALSE, ...){        
  
      fields &lt;- names(getRefClass(class(src))$fields())
      out &lt;- lapply(fields, function(x.field){
          src$field(x.field)        
      })
      names(out) &lt;- fields
  
      if(do.deep){
          out &lt;- lapply(out, function(x){
              out &lt;- x
              if(inherits(x, "MyVirtual")){
                  out &lt;- objectCoerce(src=x, to=to, do.deep=do.deep, .ARGS=.ARGS)
              }     
              return(out)
          })
      }
  
      return(out)
  
      }
  )
  </code></pre>
  
  <h2>Test Run</h2>
  
  <pre><code>x &lt;- new("B", x.a=new("A", x="hello world!"), x.b=1:5, 
      x.c=data.frame(a=c(TRUE, TRUE, FALSE)))
  
  &gt; objectCoerce(src=x, to="list")
  $x.a
  Reference class object of class "A"
  Field "x":
  [1] "hello world!"
  
  $x.b
  [1] 1 2 3 4 5
  
  $x.c
        a
  1  TRUE
  2  TRUE
  3 FALSE
  
  &gt; objectCoerce(src=x, to="list", do.deep=TRUE)
  $x.a
  $x.a$x
  [1] "hello world!"
  
  
  $x.b
  [1] 1 2 3 4 5
  
  $x.c
        a
  1  TRUE
  2  TRUE
  3 FALSE
  </code></pre>