R语言 在环路内分配S4插槽

4smxwvx5  于 2023-06-27  发布在  其他
关注(0)|答案(1)|浏览(116)

如何根据预定义列表为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调用?

zxlwwiss

zxlwwiss1#

如果您查看?slot帮助页面(从?"@"帮助页面链接),您似乎可以执行以下操作:

slot(.Object, i) <- mySlotValues[[i]]

通常,将代码连接为字符串(如您使用str_c(".Object@", i)所尝试的那样)不起作用,除非您在结果字符串上使用eval(parse(...))。这是最好避免的。(在这种情况下,由于您正在向解析的字符串赋值,因此还需要使用assign()或将赋值作为字符串的一部分包含在内。
你的do.call是一个好主意,是相当接近。如果使用函数"@<-"而不是仅使用<-,它可能也会工作。分配给索引/项目/插槽有自己的功能,将访问操作符(如$[[[names()或在这种情况下@)与分配组合在一起。在@<-函数上使用do.call看起来像这样,也可以工作,但它有点难以阅读。

do.call("@<-", list(object = ".Object", name = i, value = mySlotValues[[i]]))

相关问题