๐ŸŽ“ A1Learner
๐Ÿ”
0 of 27 lessons completed

R Reference Inheritance

Reference inheritance builds a new reference class on top of an existing one. The child class keeps the fields and methods of its parent and adds its own.

The child holds both fields

StepCounter names Counter in contains = and adds a step field. The new object holds the inherited count and its own step.

Counter <- suppressMessages(setRefClass("Counter", fields = list(count = "numeric"), methods = list(bump = function() {
  .self$count <- .self$count + 1
})))
StepCounter <- suppressMessages(setRefClass("StepCounter", contains = "Counter", fields = list(step = "numeric"), methods = list(add_step = function() {
  .self$count <- .self$count + .self$step
})))
s <- StepCounter$new(count = 10, step = 5)
print(s$count)
print(s$step)

The inherited method still runs

bump is defined on Counter and never repeated on StepCounter. Calling it on the child object moves the inherited count from 10 to 11.

Counter <- suppressMessages(setRefClass("Counter", fields = list(count = "numeric"), methods = list(bump = function() {
  .self$count <- .self$count + 1
})))
StepCounter <- suppressMessages(setRefClass("StepCounter", contains = "Counter", fields = list(step = "numeric"), methods = list(add_step = function() {
  .self$count <- .self$count + .self$step
})))
s <- StepCounter$new(count = 10, step = 5)
s$bump()
print(s$count)

The child adds its own method

add_step is defined only on StepCounter. It adds the step field to the count field through .self.

Counter <- suppressMessages(setRefClass("Counter", fields = list(count = "numeric"), methods = list(bump = function() {
  .self$count <- .self$count + 1
})))
StepCounter <- suppressMessages(setRefClass("StepCounter", contains = "Counter", fields = list(step = "numeric"), methods = list(add_step = function() {
  .self$count <- .self$count + .self$step
})))
s <- StepCounter$new(count = 10, step = 5)
s$add_step()
print(s$count)

A child object prints all its fields

print shows the child class name first. Both the inherited count field and the own step field appear in the dump.

Counter <- suppressMessages(setRefClass("Counter", fields = list(count = "numeric"), methods = list(bump = function() {
  .self$count <- .self$count + 1
})))
StepCounter <- suppressMessages(setRefClass("StepCounter", contains = "Counter", fields = list(step = "numeric"), methods = list(add_step = function() {
  .self$count <- .self$count + .self$step
})))
s <- StepCounter$new(count = 4, step = 2)
print(s)

Example

Counter <- suppressMessages(setRefClass("Counter", fields = list(count = "numeric"), methods = list(bump = function() {
  .self$count <- .self$count + 1
})))
StepCounter <- suppressMessages(setRefClass("StepCounter", contains = "Counter", fields = list(step = "numeric"), methods = list(add_step = function() {
  .self$count <- .self$count + .self$step
})))
game <- StepCounter$new(count = 0, step = 10)
game$bump()
print(game$count)
game$add_step()
print(game$count)
game$add_step()
print(game$count)

Key points

  • contains = names the parent reference class inside a setRefClass() call.
  • The child class holds every field of the parent class.
  • The child class can call every method of the parent class.
  • The child class adds its own fields beside the inherited ones.
  • The child class adds its own methods beside the inherited ones.
  • A child object prints with its own class name and all of its fields.
  • Each definition stays wrapped in suppressMessages() so the output stays clean.

In this example, game starts at 0 with a step of 10. The inherited bump call takes the count to 1, and each add_step call adds 10 more.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท rdrr.io R Snippets

Exercise

What does a child reference class get from the parent named in contains = ?