[R] S4 method dispatch: coercion of arguments with setAs defined

Martin Morgan mtmorgan at fhcrc.org
Thu Aug 6 14:42:08 CEST 2009


Hi Renaud --

Renaud Gaujoux <renaud at mancala.cbio.uct.ac.za> writes:

> Hi list,
>
> I've got a class B that contains a slot obj of class A. I'd like to be
> able to call all the methods of class A directly on objects of class B
> as if I had called the method on slot obj. This without overloading
> all methods of class A to work on class B.
> I don't define B as an extension of A, because I want class B to also
> work with objects of classes that inherit from class A and that I
> don't know the names.
>
> So I tried to dispatch the methods of class A to slot obj using
> function setAs as follows:
>
> setClass('A', representation(number='numeric'))
> setGeneric('getNumber', function(object) standardGeneric('getNumber'))
> setMethod('getNumber', 'A', function(object) object at number)
>
> setClass('B', representation(obj='A', extra='list'))
> setAs('B', 'A', def= function(from) from at obj )
>
> objB <- new('B', obj=new('A', number=10))
> getNumber(objB)
>
> But get the error:
>
> Error in function (classes, fdef, mtable)  :
>   unable to find an inherited method for function "getNumber", for
> signature "B"
>
> I thought the dispatch procedure in S4 would try to find a way to
> coerce objects of class 'B' into the closest class usable with the
> given method (in that case into an object of class 'A'). I expected it
> to internally do:
>
> getNumber(as(objB, 'A'))
>
> Am I thinking wrong or do I need to do another thing to make it work?

setAs defines a method for coercing from one object to another,
without defining an inheritance.

You can use 'setIs'

setClass('A', representation(number='numeric'))
setGeneric('number', function(object) standardGeneric('number'))
setMethod('number', 'A', function(object) object at number)

setClass('B', representation(obj='A', extra='list'))

setIs("B", "A",
      test=function(object) TRUE,
      coerce=function(object) slot(object, "obj"),
      replace=function(object, value) {
          slot(object, "obj") <- value
          object
      })

to define an inheritance relationship:

> objB <- new('B', obj=new('A', number=10))
> number(objB)
[1] 10

This is not something I usually do (are all A methods appropriate for
B's slot 'obj'?) and at least in my hands there seem to be some rough
edges

setGeneric("number<-",
           function(object, value) standardGeneric("number<-"))
setReplaceMethod("number", "A", function(object, value) {
    slot(object, "number") <- value
    object
})
                   
> number(objB) <- 20
> is(objB, "B")
[1] FALSE

Martin

> Thanks
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

-- 
Martin Morgan
Computational Biology / Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N.
PO Box 19024 Seattle, WA 98109

Location: Arnold Building M1 B861
Phone: (206) 667-2793




More information about the R-help mailing list