引用列表 class 对象在更改初始化对象时没有更改

Lists of reference class objects are not changing when the objects they were initialized with are changed

我有一个引用 class 对象的列表,我希望当我更改其中一个用于初始化列表的对象时,列表中的相应条目也应该更改。情况并非如此,如以下示例代码所示,如​​果我列出 squaretriangle,然后将 square 更改为 octagon。该列表仍将分别具有 4 边和 3 边的多边形。反之亦然。如果我更改列表的元素,初始变量保持不变。有谁知道这是为什么,或者是否有解决办法?谢谢!

Polygon <- setRefClass("Polygon", fields = c("sides"))
square <- Polygon$new(sides = 4)
triangle <- Polygon$new(sides = 3)
octagon <- Polygon$new(sides = 8)

pList <-list(square,triangle)

print(pList)
# [[1]] Reference class object of class "Polygon"
# Field "sides": [1] 4
# [[2]]    # Reference class object of class "Polygon"
# Field "sides":  [1] 3

square<-octagon
# Reference class object of class "Polygon"
# Field "sides":  [1] 8

square #the variable square changes
# Reference class object of class "Polygon"
# Field "sides": [1] 8

pList # but the entry in pList does now.
# [[1]] Reference class object of class "Polygon"
# Field "sides": [1] 4
# [[2]] Reference class object of class "Polygon"
# Field "sides":  [1] 3

#the same is true the other way around, changing the item corresponding to triangle in the list, 
#does not change the object triangle
triangle$sides #3
pList[[2]]$sides #3
pList[2]<-octagon
pList[[2]]$sides #8
triangle$sides #3

有谁知道这是为什么,或者是否有解决办法?

如果我更改对象的各个字段,更改确实会传播,如下面的代码所示,但实际上我正在使用的 classes 比简单的多边形 class 复杂得多在这里使用,因此更改每个对象内的所有字段对我来说并不是一个真正的解决方案。

square <- Polygon$new(sides = 4)
triangle <- Polygon$new(sides = 3)
octagon <- Polygon$new(sides = 8)
pList <-list(square,triangle)

#changing the list element changes the variable triangle
triangle$sides #3
pList[[2]]$sides#3
pList[[2]]$sides<-12
pList[[2]]$sides #12
triangle$sides #12

square <- Polygon$new(sides = 4)
triangle <- Polygon$new(sides = 3)
octagon <- Polygon$new(sides = 8)
pList <-list(square,triangle)

#changing the variable triangle changes the list element
triangle$sides #3
pList[[2]]$sides#3
triangle$sides<-12
pList[[2]]$sides #12
triangle$sides #12

列表条目是值而不是 references/pointers。 ReferenceClass 对象引用(或指向)与其关联的数据(即字段)。

如果您想在列表中编辑 "class pointers" 而不直接接触列表对象,新的 "PolygonPointer" class 可能是您的解决方法:

PolygonPointer <- setRefClass("PolygonPointer", fields = list(target = "Polygon"))

pointer1 <- PolygonPointer(target = square)
pointer2 <- PolygonPointer(target = triangle)

lst <- list(pointer1, pointer2)

pointer1$target <- octagon

输出为:

> lst
[[1]]
Reference class object of class "PolygonPointer"
Field "target":
Reference class object of class "Polygon"
Field "sides":
[1] 8

[[2]]
Reference class object of class "PolygonPointer"
Field "target":
Reference class object of class "Polygon"
Field "sides":
[1] 3

但请注意,这样的构造是危险的 - 例如,默认复制构造函数执行 "deep copy",同时复制指向的对象。例如:

pointer3 <- pointer1$copy()
pointer3 <- triangle
pointer1 # still points to the octagon

如果您只想复制指针本身而不是其引用的对象,则必须覆盖 PolygonPointer 的复制构造函数。