2

Is it possible to call or set values for more then one slot?

A<-setClass(Class="A",slot=c(name="character",type="character"))
a<-A()
slot(object,c("name","type"),check=T)

Do I have to write own getSlot and setSlot methods? And how to that in R5?

AB <- setRefClass("AB", fields=c(name="character"),
                  methods=list(getName=AB.getName)
                  )

AB.getName<-function(object){
  object$name
}

a<-AB(name="abc")
AB.getName(a)
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
Klaus
  • 1,946
  • 3
  • 19
  • 34

2 Answers2

4

In S4, the default initialize method allows one to write

A <- setClass(Class="A", slot=c(name="character",type="character"))
a <- A(name="abc", type="def")
initialize(a, name="cde", type="fgh")

Your own initialize methods (if any -- I think it's usually best to avoid them) have to be written to allow for this use. There is no default way to convert an S4 representation to a list.

You could incorporate these ideas into your own generics / methods with something like

setGeneric("values", function(x, ...) standardGeneric("values"))
setMethod("values", "A", function(x, ...) {
    slts = slotNames(x)
    lapply(setNames(slts, slts), slot, object=x)
})

setGeneric("values<-", function(x, ..., value) standardGeneric("values<-"))
setReplaceMethod("values", c(x="A", value="list"), function(x, ..., value) {
    do.call("initialize", c(x, value))
})

with

> a <- A(name="abc", type="def")
> values(a)  = list(name="cde", type="fgh")
> values(a)
$name
[1] "cde"

$type
[1] "fgh"
Community
  • 1
  • 1
Martin Morgan
  • 45,935
  • 7
  • 84
  • 112
  • Thx, that is what I suggest that there is no vectorized function for that. – Klaus Sep 05 '13 at 13:48
  • @Klaus: You might want to look at the `modifyList` function in lattice for ideas about "targeted" modification of recursive structures. – IRTFM Sep 05 '13 at 14:30
4

This answer applies to reference classes.

Let's start with the simplest definition of AB, without any methods.

AB <- setRefClass(
  "AB", 
  fields = list(
    name = "character"
  )
)

You can retrieve the value of the name field in the same way you would a list.

ab <- AB$new(name = "ABC")
ab$name
## [1] "ABC"
(ab$name <- "ABCD")
## [1] "ABCD"

It is possible to autogenerate accessor methods to get and set the name field.

AB$accessors("name")
ab$getName()
ab$setName("ABCDE")

This is really pointless though since it has the exactly same behaviour as before, but with more typing. What can be useful is to do input checking (or other custom behaviour) when you set a field. To do this, you can add a setName method that you write yourself.

AB$methods(
  setName = function(x) 
  {
    if(length(x) > 1)
    {
      warning("Only using the first string.")
      x <- x[1]
    }
    name <<- x
  }
)
ab$setName(letters)
## Warning message:
## In ab$setName(letters) : Only using the first string.

It is also possible (and usually more useful) to define this method when you assign the reference class template.

AB <- setRefClass(
  "AB", 
  fields = list(
    name = "character"
  ), 
  methods = list(
    setName = function(x) 
    {
      if(length(x) > 1)
      {
        warning("Only using the first string.")
        x <- x[1]
      }
      name <<- x
    }
  )
)

Response to comment:

Yes that works, but:

getFieldNames is more maintainable if implemented as names(AB$fields()).

When defining fields in setRefClass, use a list. For example, list(name="character", var2="character").

When assigning an instance of a reference class, use new. For example, AB$new(name="abc",var2="abc")

Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
  • So I have to folow this principle? 'AB.getFields<-function(){ return(c(name,var2)) } AB.getFieldNames<-function(){ return(c("name","var2")) } AB <- setRefClass("AB", fields=c(name="character", var2="character"), methods=list(getFields=AB.getFields ,setFields=AB.setFields) ) AB.setFields<-function(fields){ name<<-fields["name"] var2<<-fields["var2"] } a<-AB(name="abc",var2="abc"); a$getFields(); fields<-c(name="aaa",var2="bbb"); a$setFields(fields); a$getFields();' – Klaus Sep 05 '13 at 13:39
  • Many thx for help. To find information about it, is much harder then to find it for Java, PHP or some other commen language. – Klaus Sep 05 '13 at 14:37
  • @Klaus The help for reference classes is very limited at the moment. Start with the `?ReferenceClasses` help page and Chapter 16 of my book, Learning R. :) http://shop.oreilly.com/product/0636920028352.do – Richie Cotton Sep 05 '13 at 15:18