test_that("Inheritance", {
AC <- R6Class("AC",
portable = TRUE,
public = list(
x = 0,
z = 0,
initialize = function(x) self$x <- x,
getx = function() self$x,
getx2 = function() self$x*2,
getprivateA = function() private
),
private = list(
getz = function() self$z,
getz2 = function() self$z*2
),
active = list(
x2 = function(value) {
if (missing(value)) return(self$x * 2)
else self$x <- value/2
},
x3 = function(value) {
if (missing(value)) return(self$x * 3)
else self$x <- value/3
}
)
)
BC <- R6Class("BC",
portable = TRUE,
inherit = AC,
public = list(
y = 0,
z = 3,
initialize = function(x, y) {
super$initialize(x)
self$y <- y
},
getx = function() self$x + 10,
getprivateB = function() private
),
private = list(
getz = function() self$z + 10
),
active = list(
x2 = function(value) {
if (missing(value)) return(self$x + 2)
else self$x <- value-2
}
)
)
B <- BC$new(1, 2)
# Environment checks
eval_env <- environment(B$getx)
super_bind_env <- eval_env$super
super_eval_env <- environment(super_bind_env$getx)
expect_identical(parent.env(super_bind_env), emptyenv())
expect_identical(parent.env(super_eval_env), environment())
expect_identical(super_eval_env$self, B)
expect_identical(super_eval_env$private, B$getprivateA())
expect_identical(B$getprivateA(), B$getprivateB())
# Overridden public method
expect_identical(eval_env, environment(B$getx))
# Inherited public method
environment(B$getx2)
expect_identical(B, environment(B$getx2)$self)
# Overridden private method
expect_identical(eval_env, environment(B$getprivateA()$getz))
# Inherited private method - should have same eval env as inherited public
expect_identical(environment(B$getx2), environment(B$getprivateA()$getz2))
# Behavioral tests
# Overriding literals
expect_identical(B$x, 1)
expect_identical(B$y, 2)
expect_identical(B$z, 3) # Subclass value overrides superclass value
# Methods
expect_identical(B$getx(), 11) # Overridden public method
expect_identical(B$getx2(), 2) # Inherited public method
expect_identical(B$getprivateA()$getz(), 13) # Overriden private method
expect_identical(B$getprivateA()$getz2(), 6) # Inherited private method
# Active bindings
expect_identical(B$x2, 3) # Overridden
expect_identical(B$x3, 3) # Inherited
# Classes
expect_identical(class(B), c("BC", "AC", "R6"))
})
test_that("Inheritance: superclass methods", {
AC <- R6Class("AC",
portable = TRUE,
public = list(
x = 0,
initialize = function() {
self$inc_x()
private$inc_y()
self$incz
},
inc_x = function() self$x <- self$x + 1,
inc = function(val) val + 1,
pinc = function(val) private$priv_inc(val), # Call private inc method
gety = function() private$y,
z = 0
),
private = list(
y = 0,
inc_y = function() private$y <- private$y + 1,
priv_inc = function(val) val + 1
),
active = list(
incz = function(value) {
self$z <- z + 1
}
)
)
BC <- R6Class("BC",
portable = TRUE,
inherit = AC,
public = list(
inc_x = function() self$x <- self$x + 2,
inc = function(val) super$inc(val) + 20
),
private = list(
inc_y = function() private$y <- private$y + 2,
priv_inc = function(val) super$priv_inc(val) + 20
),
active = list(
incz = function(value) {
self$z <- self$z + 2
}
)
)
B <- BC$new()
# Testing overrides
expect_identical(B$x, 2) # Public
expect_identical(B$gety(), 2) # Private
expect_identical(B$z, 2) # Active
# Calling superclass methods
expect_identical(B$inc(0), 21)
expect_identical(B$pinc(0), 21)
# Multi-level inheritance
CC <- R6Class("CC",
portable = TRUE,
inherit = BC,
public = list(
inc_x = function() self$x <- self$x + 3,
inc = function(val) super$inc(val) + 300
),
private = list(
inc_y = function() private$y <- private$y + 3,
priv_inc = function(val) super$priv_inc(val) + 300
),
active = list(
incz = function(value) {
self$z <- self$z + 3
}
)
)
C <- CC$new()
# Testing overrides
expect_identical(C$x, 3) # Public
expect_identical(C$gety(), 3) # Private
expect_identical(C$z, 3) # Active
# Calling superclass methods (two levels)
expect_identical(C$inc(0), 321)
expect_identical(C$pinc(0), 321)
# Classes
expect_identical(class(C), c("CC", "BC", "AC", "R6"))
})
test_that("Inheritance: enclosing environments for super$ methods", {
encA <- new.env()
encB <- new.env()
encC <- new.env()
encA$n <- 1
encB$n <- 20
encC$n <- 300
AC <- R6Class("AC",
portable = TRUE,
parent_env = encA,
public = list(
x = 0,
initialize = function() {
self$x <- self$get_n()
},
get_n = function() n,
priv_get_n = function(val) private$get_n_priv()
),
private = list(
get_n_priv = function() n
),
active = list(
active_get_n = function() n
)
)
A <- AC$new()
expect_identical(A$x, 1)
expect_identical(A$get_n(), 1)
expect_identical(A$priv_get_n(), 1)
expect_identical(A$active_get_n, 1)
BC <- R6Class("BC",
portable = TRUE,
parent_env = encB,
inherit = AC,
public = list(
x = 0,
initialize = function() {
super$initialize()
},
get_n = function() n + super$get_n(),
priv_get_n = function(val) private$get_n_priv()
),
private = list(
get_n_priv = function() n + super$get_n_priv()
),
active = list(
active_get_n = function() n + super$active_get_n
)
)
B <- BC$new()
expect_identical(B$x, 21)
expect_identical(B$get_n(), 21)
expect_identical(B$priv_get_n(), 21)
expect_identical(B$active_get_n, 21)
CC <- R6Class("CC",
portable = TRUE,
parent_env = encC,
inherit = BC,
public = list(
x = 0,
initialize = function() {
super$initialize()
},
get_n = function() n + super$get_n(),
priv_get_n = function(val) private$get_n_priv()
),
private = list(
get_n_priv = function() n + super$get_n_priv()
),
active = list(
active_get_n = function() n + super$active_get_n
)
)
C <- CC$new()
expect_identical(C$x, 321)
expect_identical(C$get_n(), 321)
expect_identical(C$priv_get_n(), 321)
expect_identical(C$active_get_n, 321)
})
test_that("Inheritance: enclosing environments for inherited methods", {
encA <- new.env()
encB <- new.env()
encC <- new.env()
encA$n <- 1
encB$n <- 20
encC$n <- 300
AC <- R6Class("AC",
portable = TRUE,
parent_env = encA,
public = list(
get_n = function() n
)
)
A <- AC$new()
expect_identical(A$get_n(), 1)
BC <- R6Class("BC",
portable = TRUE,
parent_env = encB,
inherit = AC
)
B <- BC$new()
# Since this inherits A's get_n() method, it should also inherit the
# environment in which get_n() runs. This is necessary for inherited methods
# to find methods from the correct namespace.
expect_identical(B$get_n(), 1)
CC <- R6Class("CC",
portable = TRUE,
parent_env = encC,
inherit = BC,
public = list(
get_n = function() n + super$get_n()
)
)
C <- CC$new()
# When this calls super$get_n(), it should get B's version of get_n(), which
# should in turn run in A's environment, returning 1. Add C's value of n, and
# the total is 301.
expect_identical(C$get_n(), 301)
})
test_that("Inheritance hierarchy for super$ methods", {
AC <- R6Class("AC", portable = TRUE,
public = list(n = function() 0 + 1)
)
expect_identical(AC$new()$n(), 1)
BC <- R6Class("BC", portable = TRUE,
public = list(n = function() super$n() + 10),
inherit = AC
)
expect_identical(BC$new()$n(), 11)
CC <- R6Class("CC", portable = TRUE,
inherit = BC
)
# This should equal 11 because it inherits BC's n(), which adds 1 to AC's n()
expect_identical(CC$new()$n(), 11)
# Skipping one level of inheritance ---------------------------------
AC <- R6Class("AC", portable = TRUE,
public = list(n = function() 0 + 1)
)
expect_identical(AC$new()$n(), 1)
BC <- R6Class("BC", portable = TRUE,
inherit = AC
)
expect_identical(BC$new()$n(), 1)
CC <- R6Class("CC", portable = TRUE,
public = list(n = function() super$n() + 100),
inherit = BC
)
# This should equal 101 because BC inherits AC's n()
expect_identical(CC$new()$n(), 101)
DC <- R6Class("DC", portable = TRUE,
inherit = CC
)
# This should equal 101 because DC inherits CC's n(), and BC inherits AC's n()
expect_identical(DC$new()$n(), 101)
# Skipping two level of inheritance ---------------------------------
AC <- R6Class("AC", portable = TRUE,
public = list(n = function() 0 + 1)
)
expect_identical(AC$new()$n(), 1)
BC <- R6Class("BC", portable = TRUE, inherit = AC)
expect_identical(BC$new()$n(), 1)
CC <- R6Class("CC", portable = TRUE, inherit = BC)
expect_identical(CC$new()$n(), 1)
})
test_that("sub and superclass must both be portable or non-portable", {
AC <- R6Class("AC", portable = FALSE, public = list(x=1))
BC <- R6Class("BC", portable = TRUE, inherit = AC)
expect_error(BC$new())
AC <- R6Class("AC", portable = TRUE, public = list(x=1))
BC <- R6Class("BC", portable = FALSE, inherit = AC)
expect_error(BC$new())
})
test_that("Inheritance is dynamic", {
AC <- R6Class("AC",
public = list(x = 1, initialize = function() self$x <<- self$x + 10)
)
BC <- R6Class("BC", inherit = AC)
expect_identical(BC$new()$x, 11)
AC <- R6Class("AC",
public = list(x = 2, initialize = function() self$x <<- self$x + 20)
)
expect_identical(BC$new()$x, 22)
# BC doesn't contain AC, and it has less stuff in it, so it should be smaller
# than AC.
if (requireNamespace("lobstr", quietly = TRUE)) {
expect_true(lobstr::obj_size(BC) < lobstr::obj_size(AC))
}
})
test_that("Private env is created when all private members are inherited", {
# Private contains fields only
AC <- R6Class("AC",
public = list(getx = function() private$x),
private = list(x = 1)
)
BC <- R6Class("BC", inherit = AC)
expect_identical(BC$new()$getx(), 1)
# Private contains functions only
AC <- R6Class("AC",
public = list(getx = function() private$x()),
private = list(x = function() 1)
)
BC <- R6Class("BC", inherit = AC)
expect_identical(BC$new()$getx(), 1)
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.