I'm wondering how to include an S3 object as a data member in an S4 object, i.e. using composition instead of inheritance. Here's my code snippet.
library(randomForest)
set.seed(1337)
setClass("TestManager", slots = c(
hp = "numeric",
rfObj = "randomForest")
)
setGeneric("doIt", function(obj) standardGeneric("doIt"))
setMethod("doIt", "TestManager", function(obj) {
response <- rep(c(0, 1), times = 50) # a vector of length 100
predictors <- matrix(runif(200), nrow = 100, ncol = 2) # a matrix of dimension 100 x 2
# package "randomForest" has a function "randomForest"
# that returns an object of S3 class "randomForest"
obj@rfObj <- randomForest::randomForest(predictors, response) # <- ERROR!
return(obj)
})
obj <- new("TestManager", hp = 100)
obj <- doIt(obj)
This would lead to an error message:
Error in validObject(.Object) :
invalid class “TestManager” object: undefined class for slot "rfObj" ("randomForest")
In addition: Warning message:
Error in validObject(.Object) :
invalid class “TestManager” object: undefined class for slot "rfObj" ("randomForest")
One options is just to use "ANY" as the slot type. This would avoid the type checking
setClass("TestManager", slots = c(
hp = "numeric",
rfObj = "ANY")
)
Otherwise you can use
setOldClass("randomForest")
to have S4 recognize the randomForest class type. But in your example you don't seem to be initializing that slot and there's no such thing as an "empty" random forest object so you would still get the error on initialization. If you want to allow NULL values, you can build a union class
setOldClass("randomForest")
setClassUnion("randomForestOrNULL", c("randomForest", "NULL"))
setClass("TestManager", slots = c(
hp = "numeric",
rfObj = "randomForestOrNULL")
)
Then these will work
obj <- new("TestManager", hp = 100)
obj@rfObj # NULL
obj <- doIt(obj)
obj@rfObj
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With