I have a reference class that I'd to use as an object inside another reference class. Example:
class_1 <- setRefClass( Class = "class_1"
, fields = list(nickname = "character", version = "character" )
, methods = list(
initializer = function(nickname, version) {
nickname <<- nickname
version <<- version
}
)
)
class_2 <- setRefClass( Class = "class_2"
, fields = c( version = "character"
, nickname = "character"
, class_1_item = "class_1" )
, methods = list(
initializer = function(class_2_nickname = "B", class_2_version = "V2") {
class_1_item <<- class_1$new(class_2_nickname, class_1_version)
nickname <<- class_2_nickname
version <<- class_2_version
}
)
)
#######
class_2_obj <- class_2$new(nickname = "A", version = "V1")
class_1_obj <- class_1$new(nickname = "A", version = "V1")
class_2_obj2 <- class_2$new()
When I invoke the first line after the comment markings, it creates a class_2 object with a class_1 object inside of it, but it never initializes the fields to the object class_1_item that has its constructor called as part of the first line. Yet when I call the constructor directly in line 2 (outside of the class 2 constructor), it initializes those fields just fine. Lastly, when I call the constructor in line 3 without arguments, it doesn't even grab the default arguments and leaves everything null.
I feel like there's something fundamental about R classes that makes them completely different from C/Python/Java classes that I'm not getting. I don't understand what the object "class_1" is referring to as an object when I use the assignment operator with $setRefClass()$. Also, I feel like I don't understand in what cases the "<<-" operator is intended to be used in this context versus the "<-" operator.
What am I missing?
The initialize process for S4 reference classes has always confused me, so there may be a better solution. You have to use <<-
instead of <-
because the normal assignment operator would only make a local assignment - local to your init method. However you want to replace the fields in the object which are in the enclosing environment of any method defined for your object. To make an assignment in the enclosing environment you need <<-
. An alternative is the use of .self
which I use for illustration below - as far as I know there is no difference other than preference.
Also I modified your example such that the init process aligns with your expectation. The initialize section of the setRefClass
function may be worth reading. I have no understanding of what a initializer
method as you defined it does in contrast to the initialize
method but I believe it is the latter which you really want. Furthermore I could not make any sense out of the class_1_version
object you are referring to but which seems to be defined nowhere. But I hope the following helps anyway.
class_1 <- setRefClass(
Class = "class_1",
fields = list(nickname = "character", version = "character" ),
methods = list(
initialize=function(nickname = NA_character_, version = NA_character_) {
.self$nickname <- nickname
.self$version <- version
}
)
)
class_2 <- setRefClass(
Class = "class_2",
fields = c(
version = "character",
nickname = "character",
class_1_item = "class_1"
),
methods = list(
initialize=function(nickname = NA_character_, version = NA_character_) {
.self$class_1_item <- class_1$new(nickname, version)
.self$nickname <- nickname
.self$version <- version
}
)
)