当我修改复制的(复制的)Geom 对象时,这也会修改底层的原始 Geom。为什么?

When I modify a duplicated (copied) Geom object, this also modifies the underlying original Geom. Why?

当我修改复制的 Geom 对象的一部分时,这也会修改底层的原始 Geom。为什么?

(非常感谢用户 Stefan 通过评论我之前已删除的问题来识别此问题)。

library(ggplot2)
GeomFunction$required_aes
#> [1] "x" "y"
GeomFunction2 <- GeomFunction
GeomFunction2$required_aes <- c("x", "y", "fun")
GeomFunction$required_aes
#> [1] "x"   "y"   "fun"

reprex package (v2.0.1)

创建于 2022-01-09

因为 ggproto class 对象是环境而不是类似列表的结构,可以用 is.environment(GeomFunction) 检查。环境不遵循修改时复制启发式方法,例如矢量坚持。

为修改目的制作副本的正确方法是使用 ggproto 构造函数。从技术上讲,您正在创建 GeomFunction.

的子实例
library(ggplot2)

GeomFunction2 <- ggproto(NULL, GeomFunction)
GeomFunction2$required_aes <- c("x", "y", "fun")

identical(GeomFunction$required_aes, GeomFunction2$required_aes)
#> [1] FALSE

reprex package (v2.0.1)

创建于 2022-01-09

此外,因为ggproto对象是环境,我们可以使用ls()查看它们包含的内容。

ls(GeomFunction2)
#> [1] "required_aes" "super"
ls(GeomFunction)
#> [1] "draw_panel" "super"
ls(Geom)
#>  [1] "aesthetics"      "default_aes"     "draw_group"      "draw_key"       
#>  [5] "draw_layer"      "draw_panel"      "extra_params"    "handle_na"      
#>  [9] "non_missing_aes" "optional_aes"    "parameters"      "required_aes"   
#> [13] "setup_data"      "setup_params"    "use_defaults"

可以看到层次结构中的每一层都只包含了相对于parent的变化,以及一个神秘的super对象,也就是一个函数。当调用 super 函数时,您可以看到它检索了父 class.

class(GeomFunction2$super())
#> [1] "GeomFunction" "GeomPath"     "Geom"         "ggproto"      "gg"

reprex package (v2.0.1)

创建于 2022-01-09

Geom 中缺少 super 对象表明 Geom 是根 class。

ggproto class 存在的原因是允许扩展重用大块代码,而不必从头开始构建它们。理论上,ggproto 类似于 R6 或参考 class 面向对象编程,但我认为 R6/reference classes 有一些缺点,不允许跨包继承它们的 classes.