是否可以在 S4 class 中有一个 S3 插槽?

Is it possible to have an S3 slot in an S4 class?

我想知道如何将 S3 对象作为数据成员包含在 S4 对象中,即使用 composition 而不是 inheritance .这是我的代码片段。

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)

这会导致错误消息:

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") 

一个选项就是使用 "ANY" 作为插槽类型。这将避免类型检查

setClass("TestManager", slots = c(
    hp = "numeric",
    rfObj = "ANY")
)

否则你可以使用

setOldClass("randomForest")

让 S4 识别 randomForest class 类型。但是在您的示例中,您似乎没有初始化该插槽并且没有 "empty" 随机森林对象这样的东西,因此您仍然会在初始化时遇到错误。如果你想允许 NULL 值,你可以构建一个 union class

setOldClass("randomForest")
setClassUnion("randomForestOrNULL", c("randomForest", "NULL"))
setClass("TestManager", slots = c(
  hp = "numeric",
  rfObj = "randomForestOrNULL")
)

那么这些就可以了

obj <- new("TestManager", hp = 100)
obj@rfObj # NULL
obj <- doIt(obj)
obj@rfObj