diff --git a/R/clone.R b/R/clone.R index 0027a6b..f3a4176 100644 --- a/R/clone.R +++ b/R/clone.R @@ -1,6 +1,6 @@ # This function will be added as a method to R6 objects, with the name '.clone', # and with the environment changed. -generator_funs$.clone_method <- function(deep = FALSE) { +generator_funs$.clone_method <- function(deep = FALSE, post_clone_args = list()) { # Need to embed these utility functions inside this closure because the # environment of this function will change. @@ -367,6 +367,10 @@ generator_funs$.clone_method <- function(deep = FALSE) { class(new_1_binding) <- class(old_1_binding) + if (has_private && is.function(new[[1]]$private$post_clone)) { + do.call(new[[1]]$private$post_clone, post_clone_args) + } + new_1_binding } diff --git a/tests/testthat/test-clone.R b/tests/testthat/test-clone.R index b98930d..048127c 100644 --- a/tests/testthat/test-clone.R +++ b/tests/testthat/test-clone.R @@ -45,6 +45,74 @@ test_that("Custom clone() can call .clone() and modify the original", { expect_equal(b$x, 1) }) +test_that("post_clone() can change fields on new object", { + AC <- R6Class("AC", + public = list( + x = 1, + increment_counter = function() { + private$counter <- private$counter + 1 + }, + get_counter = function() { + private$counter + } + ), + private = list( + counter = 0, + post_clone = function() { + # reset the counter on clone() + private$counter <- 0 + } + ) + ) + + a <- AC$new() + a$increment_counter() + b <- a$clone() + # x is cloned: + expect_equal(a$x, 1) + expect_equal(b$x, 1) + # counter is reset: + expect_equal(a$get_counter(), 1) + expect_equal(b$get_counter(), 0) +}) + +test_that("post_clone() accepts custom arguments", { + AC <- R6Class("AC", + public = list( + x = 1, + increment_counter = function() { + private$counter <- private$counter + 1 + }, + get_counter = function() { + private$counter + }, + clone = function(deep = FALSE, new_counter = 0) { + self$.clone(deep = deep, post_clone_args = list(counter = new_counter)) + } + ), + private = list( + counter = 0, + post_clone = function(counter) { + # reset the counter on clone() + private$counter <- counter + } + ) + ) + + a <- AC$new() + expect_equal(a$get_counter(), 0) + a$increment_counter() + expect_equal(a$get_counter(), 1) + b <- a$clone() + # x field was cloned: + expect_equal(a$x, 1) + expect_equal(b$x, 1) + # counter was reset on the copy, but not on the original: + expect_equal(a$get_counter(), 1) + expect_equal(b$get_counter(), 0) +}) + + test_that("Cloning portable objects with public only", { parenv <- new.env() AC <- R6Class("AC",