How to loop through subclasses within an R6 class

58 Views Asked by At

I'm new to the R6 classes and i'm starting to get the hang of things. However, i'm currently nesting classes and i want to loop through a list of specific nested classes. So, as shown in the example below, some of the elements of a Person class are classes themselves, like the BodyPart class, which is incorporated via the arm, leg and head elements of the Person class. The Person class also contains a list of subclasses of interest (bodyParts, as a way of grouping them). The getVolume function in the Person class loops through the list and catches the specific subclasses of interest.

A small and silly example:

BodyPart <- R6::R6Class(classname = "BodyPart",
                        public = list(
                          width = numeric(),
                          volume = numeric(),
                          initialize = function(name = NA, width = 3, volume = 2){
                            self$name <- name
                            self$width <- width
                            self$volume <- volume
                          }
                          
                        )
)

Person <- R6::R6Class(classname = "Person",
                      public = list(
                        name = character(),
                        age = numeric(),
                        bodyParts = list(),
                        arm = environment(),
                        leg = environment(),
                        head = environment(),
                        initialize = function(name = NA, age = NA, bodyParts = list("arm", "leg", "head"), arm = NA, leg = NA, head = NA){
                          self$name <- name
                          self$age <- age
                          self$bodyParts <- bodyParts
                          self$arm <- arm
                          self$leg <- leg
                          self$head <- head
                        }, 
                        getVolume = function(){
                          for(bodyPart in self$bodyParts){
                            volume <- get(bodyPart)$volume
                            print(paste(bodyPart, volume))
                          }
                        }
                      )
)

LongArm <- BodyPart$new()
MediumLeg <- BodyPart$new()
CubeHead <- BodyPart$new()

Person <- Person$new(name = "Jake", age = 20, arm = LongArm, leg = MediumLeg, head = CubeHead)
Person$getVolume()

The code does work for classes in general (those defined outside of the Person class), but not for the attached subclasses, since i do not know how to incorporate the self$ portion in the loop.

I know the example above is a bit silly and indirect, but the idea is the same. The final plan is to allow for a custom number of subclasses (using ...), which can be selected by the bodyParts list, allowing for functions to interact with a custom number of specific subclasses at once.

Does anyone know how to select specific subclasses within a R6 class? Or might a different approach be more effective for this problem?

Many thanks in advance!

1

There are 1 best solutions below

0
Greacus On

I found quite a simple workaround: list all the bodyparts (subclasses) together and let the class take the list as a property/element. Then loop through the self$list to get whatever value you want.

so this would be:

BodyPart <- R6::R6Class(classname = "BodyPart",
                        public = list(
                          width = numeric(),
                          volume = numeric(),
                          initialize = function(name = NA, width = 3, volume = 2){
                            self$name <- name
                            self$width <- width
                            self$volume <- volume
                          }
                          
                        )
)

Person <- R6::R6Class(classname = "Person",
                      public = list(
                        name = character(),
                        age = numeric(),
                        bodyParts = list(),
                        initialize = function(name = NA, age = NA, bodyParts = NA){
                          self$name <- name
                          self$age <- age
                          self$bodyParts <- bodyParts
                        }, 
                        getVolume = function(){
                          for(bodyPart in self$bodyParts){
                            print(bodyPart$volume)
                          }
                        }
                      )
)

LongArm <- BodyPart$new()
MediumLeg <- BodyPart$new()
CubeHead <- BodyPart$new()

bodyPartsList <- c(LongArm, MediumLeg, CubHead)

Person <- Person$new(name = "Jake", age = 20, BodyParts = bodyPartsList)
Person$getVolume()

Hope this also helps for others as well!