当初始化对象更改时,引用类对象列表不会更改

时间:2015-11-16 10:55:56

标签: r reference-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

有谁知道为什么会这样或者是否有解决方法?

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

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

1 个答案:

答案 0 :(得分:0)

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

如果要在列表中编辑“类指针”而不直接触摸列表对象,可以使用新的“PolygonPointer”类来解决此问题:

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

但请注意,此类构造很危险 - 例如,默认的复制构造函数执行“深层复制”,同时复制指向的对象。例如:

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

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