У меня возникли проблемы с достижением согласованного поведения при доступе к атрибутам, прикрепленным к объектам ссылочного класса. Например,
testClass <- setRefClass('testClass',
methods = list(print_attribute = function(name) print(attr(.self, name))))
testInstance <- testClass$new()
attr(testInstance, 'testAttribute') <- 1
testInstance$print_attribute('testAttribute')
И консоль R весело печатает NULL
. Однако, если мы попробуем другой подход,
testClass <- setRefClass('testClass',
methods = list(initialize = function() attr(.self, 'testAttribute') <<- 1,
print_attribute = function(name) print(attr(.self, name))))
testInstance <- testClass$new()
testInstance$print_attribute('testAttribute')
и теперь у нас есть 1
, как и ожидалось. Обратите внимание, что требуется оператор <<-
, предположительно потому, что присвоение .self
имеет те же ограничения, что и присвоение полям ссылочного класса. Обратите внимание: если бы мы пытались назначить вне конструктора, скажем,
testClass <- setRefClass('testClass',
methods = list(set_attribute = function(name, value) attr(.self, name) <<- value,
print_attribute = function(name) print(attr(.self, name))))
testInstance <- testClass$new()
testInstance$set_attribute('testAttribute', 1)
нас бы ударили
Error in attr(.self, name) <<- value :
cannot change value of locked binding for '.self'
Действительно, документация ?setRefClass
объясняет, что
На весь объект в методе можно ссылаться по зарезервированному имени
.self
... Эти поля доступны только для чтения (нет смысла изменять эти ссылки), за одним исключением. В принципе, поле.self
можно изменить в методе$initialize
, потому что объект все еще создается на этом этапе.
Меня все это устраивает, и я согласен с авторскими решениями. Однако меня беспокоит следующее. Возвращаясь к первому примеру выше, если мы попытаемся запросить attr(testInstance, 'testAttribute')
, мы увидим из глобальной среды, что это 1
!
Предположительно, .self
, который используется в методах объекта ссылочного класса, хранится в той же области памяти, что и _16 _ - это тот же объект. Таким образом, успешно установив атрибут на testInstance
в глобальной среде, но не в качестве .self
ссылки (как показано в первом примере), не запустили ли мы случайно копию всего объекта в глобальной среде? Или способ хранения атрибутов в некотором роде «забавный»: объект может находиться в одной и той же памяти, но его атрибуты различаются в зависимости от вызывающей среды?
Я не вижу другого объяснения, почему attr(.self, 'testAttribute')
равно NULL
, а attr(testInstance, 'testAttribute')
равно 1
. Привязка .self
заблокирована раз и навсегда, но это не означает, что объект, на который он ссылается, нельзя изменить. Если это желаемое поведение, это похоже на ошибку.
Последний вопрос заключается в том, подразумевают ли предыдущие результаты attr<-
следует избегать использования объектов ссылочного класса, по крайней мере, если результирующие атрибуты используются из методов объекта.
.self
внутри объекта? Методы объектов ссылочного класса могут принимать функции в качестве аргументов (например, блоки в Ruby). - person Robert Krzyzanowski   schedule 01.04.2014.self
. Это не конкретная проблема, с которой я столкнулся, но она иллюстрирует теоретический вариант использования. В моем случае я создал подкласс объекта ссылочного класса и задался вопросом, могу ли я получить доступ к атрибутам на.self
в методе для вышеупомянутых целей оптимизации, утверждая, что метаданные, прикрепленные к объекту, не были и не должны быть полем, потому что в нем закодирована информация о Совершенно другая мета-структура обертывания, но в конечном итоге я выбрал другой, более разумный подход. - person Robert Krzyzanowski   schedule 01.04.2014