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

时间:2020-02-14 00:39:42

标签: r self s4

我有一个S4对象,该对象表示包含某些数据和同一类的其他对象的递归树结构。我还有一个递归功能,可以修改树中每个节点的两个插槽。在执行此操作时,该函数(称为“ propagate()”)会正确执行其操作:

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

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

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

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

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

  1. 我想这与R的按值调用性质有关,并且我不能影响用于调用转换函数的对象的值。那是正确的还是我只是愚蠢,这应该起作用?

  2. 是否有R魔术可以解决此问题?以某种方式调用“ assign()”函数来强制对象的新定义替换当前对象?还是什么?

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

谢谢。

1 个答案:

答案 0 :(得分:1)

要完成此工作,需要做两件事:

1)推测,递归不会永远持续下去,即某个对象在某个时刻将不包含到另一个对象的链接,因为它位于树的底部。因此,您需要其他树objs的列表为NULL的可能性。您可以通过类联合来做到这一点:

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

然后在对象的第三个插槽中使用的正确类是这个新的类联合。

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从函数中进行任何操作,因此您只修改了未保存在任何地方的对象的副本。