如何根据预定义列表为S4插槽分配值?
B1类创建为:
mySlots <- c("myA", "c")
myTypes <- c("numeric", "character")
myVals <- c(1222, "blabla")
mySlotTypes <- setNames(as.list(myTypes), as.list(mySlots))
mySlotValues <- setNames(as.list(myVals), as.list(mySlots))
setClass("B1",
do.call("representation", mySlotTypes)
)
可以使用以下方式手动分配插槽:
> x <- new("B1")
> x@myA <- 2333
> x@c <- "ddd"
> str(x)
Formal class 'B1' [package ".GlobalEnv"] with 2 slots
..@ myA: num 2333
..@ c : chr "ddd"
我尝试了两种选择:
选项A
正在尝试使用prototype分配:
setClass("B1",
do.call("representation", mySlotTypes),
do.call("prototype", mySlotValues)
)
什么是错误:
- makePrototypeFromClassDef(properties,ClassDef,immediate,where)出错:在为原型的“B1”类元素制作原型时,未能匹配相应的插槽类:myA(class“numeric”)*
选项B
尝试使用initialize方法也没有运气:
setMethod("initialize", signature = "B1",
definition = function (.Object) {
for(i in slotNames(.Object)) {
do.call("<-", list( str_c(".Object@", i), mySlotValues[[i]]))
}
return (.Object)
})
此解决方案不会出错,但根本没有初始化:
> x <- new("B1")
> str(x)
Formal class 'B1' [package ".GlobalEnv"] with 2 slots
..@ myA: num(0)
..@ c : chr(0)
有没有简单的解决方案,如何用循环友好的分配来代替手动的.Object@myA <- 1222
调用?
1条答案
按热度按时间zxlwwiss1#
如果您查看
?slot
帮助页面(从?"@"
帮助页面链接),您似乎可以执行以下操作:通常,将代码连接为字符串(如您使用
str_c(".Object@", i)
所尝试的那样)不起作用,除非您在结果字符串上使用eval(parse(...))
。这是最好避免的。(在这种情况下,由于您正在向解析的字符串赋值,因此还需要使用assign()
或将赋值作为字符串的一部分包含在内。你的
do.call
是一个好主意,是相当接近。如果使用函数"@<-"
而不是仅使用<-
,它可能也会工作。分配给索引/项目/插槽有自己的功能,将访问操作符(如$
,[
,[[
,names()
或在这种情况下@
)与分配组合在一起。在@<-
函数上使用do.call
看起来像这样,也可以工作,但它有点难以阅读。