R:从 S4 方法中更改 S4 对象

R: Changing an S4 object from within an S4 method

我有一个 S4 对象,表示包含一些数据和相同 class 的其他对象的递归树结构。我还有一个递归函数来修改树中每个节点中的两个槽。当我这样做时,该函数(称之为 "propagate()")会正确地完成它的工作:

> obj <- treeObj(4, 5)
> slotNames(obj)
[1] "x" "y" "listOfOtherTreeObjs"
> obj <- propagate(obj, 1, 4)  

我可以编写一个像这样的函数,它接受一个参数并用该数据填充树,没问题。

不过,我想要的是能够从根对象的方法中调用 propagate():

setMethod("transform", signature="treeObj",
    definition=function(object, i, j) {
         object@x <- i;  object@y <- j;
         object <- propagate(object, i, j);
         ... (do some other stuff in the tree)
    })

在此方法中,propagate() 似乎正常运行,但其结果似乎并未以在 transform() 方法定义中可检测到的方式分配给父对象。我的问题:

  1. 我想这与 R 的按值调用性质有关,我无法影响用于调用转换函数的对象的值。这是正确的还是我只是愚蠢而这应该有效?

  2. 有什么 R 魔法可以解决这个问题吗?调用 'assign()' 函数以强制对象的新定义替换当前对象的某种方式?或者什么?

  3. 是否有更 R-ish 的方法来构建我的递归对象来支持这种事情?

提前致谢。

要完成这项工作,您需要做两件事:

1) 据推测,递归不会永远持续下去,即在某个时候,一个对象不会包含到另一个对象的 link,因为它位于树的底部。因此,您需要其他树对象列表为 NULL 的可能性。您可以使用 class 联合来执行此操作:

setClassUnion("listOfOtherTreeObjsOrNULL",c("listOfOtherTreeObjs","NULL"))

然后在对象的第三个插槽中使用的正确 class 是这个新的 class 并集。

2) 当您为 transform 定义方法时,它需要看起来像这样:

function(object,i,j){
  ## do whatever you want with i and j
  if(is.null(object@listOfOtherTreeObjs)) return(object)
  else{
    object@listOfOTherTreeObjs <- lapply(object@listOfOtherTreeObjs,propagate)
    return(object)
  }
}

您的更改似乎没有生效的原因是您没有return从您的函数中获取任何内容,因此您只是修改了未保存在任何地方的对象的副本。