Thanks Martin, it's clearer now.

Indeed things get a bit dirty with replace methods. I'm wondering if it's a bug, a normal behaviour or if there is nothing to do about it? I think it's because the replace method of A into B is not called after replacing an object's slot. I imagine this would be done in method 'slot<-', wouldn't it?
See messages with the following code:

setIs("B", "A",
     test=function(object){ message("Test if B is A"); TRUE},
coerce=function(object){ message("Coerce B into A"); slot(object, "obj")},
     replace=function(object, value) {
         message("Replace slot A in B")
         slot(object, "obj") <- value
         object
     })

setGeneric("number<-", function(object, value) standardGeneric("number<-"))
setReplaceMethod("number", "A", function(object, value) {
   message("Replace number in A")
   slot(object, "number") <- value
   object
})

objB <- new('B', obj=new('A', number=10))
number(objB) <- 20

Martin Morgan wrote:
Hi Renaud --

Renaud Gaujoux <ren...@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) obj...@number)

setClass('B', representation(obj='A', extra='list'))
setAs('B', 'A', def= function(from) f...@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) obj...@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@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.



______________________________________________
R-help@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.

Reply via email to