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

时间:2019-12-10 20:10:10

标签: r s4

我想知道如何将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") 

1 个答案:

答案 0 :(得分:4)

一种选择是仅使用“ ANY”作为插槽类型。这样可以避免类型检查

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

否则,您可以使用

setOldClass("randomForest")

让S4识别randomForest类类型。但是在您的示例中,您似乎没有在初始化该插槽,并且没有“空”随机森林对象之类的东西,因此在初始化时仍然会收到错误。如果要允许NULL值,则可以构建联合类

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