2015-11-16 14 views
1

У меня есть список объектов ссылочного класса, и я ожидаю, что когда я сменил один из объектов, список которых был инициализирован, соответствующая запись в список также должен измениться. Это не так, как указано в следующем примере кода, если я делаю список из square и triangle, а затем я меняю 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 

ответ

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, если вы просто хотите, чтобы скопировать указатель itsself, а не его объект ссылки.