Search code examples
rr-s4

How can I disallow empty slots for S4 objects?


Say I have a class defined as the following:

setClass("myclass", slots = list(id="character"))

I want things to be such that the id is mandatory and myclass without an id is an invalid object. At current, I get the following:

> new("myclass")
An object of class "myclass"
Slot "id":
character(0)

I hoped that setting a validation function would help:

setValidity("myclass", function(object){
  if(length(slot(object, "id")) == 0L){
    return("You cannot do that")
  }
  return(TRUE)
})

> new("myclass")
An object of class "myclass"
Slot "id":
character(0)

But unfortunately, it seems like having empty arguments causes the validation function to be bypassed. Is there a way to invalidate this type of input?


Solution

  • The best solution I could find was to put the validation step in the constructor function (which seems a bit perverse to me):

    setMethod("initialize", "myclass", function(.Object, id){
      if(missing(id)) stop("The id is not allowed to be empty")
      .Object@id <- id
      validObject(.Object)
      return(.Object)
    })
    

    This now gives the expected results:

    > new("myclass")
    Error in .local(.Object, ...) : The id is not allowed to be empty
    > new("myclass", id = character())
    Error in validObject(.Object) : 
      invalid class “myclass” object: You cannot do that
    > new("myclass", id = "a")
    An object of class "myclass"
    Slot "id":
    [1] "a"