Suppose I have an S4 class Test
that has a single slot name
. A valid name must be at least one character long, so Test(name = "Bob")
should work but Test(name = "")
should throw an error. An undefined name should also give an error: Test()
.
My class is defined as:
Test <- setClass(
"Test",
slots = c(name = "character"),
validity = function(object) {
if (nchar(object@name) == 0) {
return("name must at least one character long")
}
T
})
Testing the class in the console, I find that my validity function is not executed for the unassigned case:
> Test(name = "Bob")
An object of class "Test"
Slot "name":
[1] "Bob"
> Test(name = "")
Error in validObject(.Object) :
invalid class “Test” object: name must at least one character long
> Test()
An object of class "Test"
Slot "name":
character(0)
How can I ensure that an error is always thrown when an invalid object is created?
One way to ensure the validity of an S4 is the use of prototype
to initialise the slots like this
Test <- setClass(
"Test",
slots = c(name = "character"),
prototype = prototype(name = 'name_default'),
validity = function(object) {
if (nchar(object@name) == 0) {
return("name must at least one character long")
}
})
Test(name = "Bob")
## An object of class "Test"
## Slot "name":
## [1] "Bob"
Test(name = '')
## Error in validObject(.Object) :
## invalid class "Test" object: name must at least one character long
Test()
## An object of class "Test"
## Slot "name":
## [1] "name_default"
another way would be to create a constructor to test the presence of name:
consTest <- function(name) {
if (missing(name)) {
stop("name is missing")
} else {
new(Class = "Test", name = name)
}
}
consTest(name = "Bob") # similar to Test(...)
consTest(name = '') # similar to Test(...)
consTest()
## Error in consTest() (from Retest.R@13#3) : name is missing