Description
(cc @clauswilke #3818 (comment))
Context
Let's say foo
is a class defined by a package other than ggplot2 (Ex: patchwork
or GGally
). foo
objects also inherit from gg
. bar
objects do not inherit from gg
You can currently perform gg_obj + foo_obj
as both objects inherit from gg
and would produce the same +.gg
method from Opt's double dispatch.
Currently, to control how the right-hand-side (foo
objects) are added, we can define ggplot_add.foo
.
Problem
However, currently we can not customize how left-hand-side objects (ex: foo_obj + gg_obj
) are added to gg
objects.
Ex: left hand side structures are not ggplot2 objects and will not work with ggplot2 internal methods
x <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
foo_obj <- structure(
list(x, x),
class = c("foo", "gg")
)
# can not customize how the theme is added
foo_obj + theme_bw()
Ex: conflicting +
methods make addition impossible
x <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
bar_obj <- structure(
list(x, x),
class = c("bar") # does not inherit from 'gg'
)
`+.bar` <- function(e1, e2) {
# only add to second plot
e1[[2]] <- e1[[2]] + e2
e1
}
# Conflicting `+` methods
bar_obj + theme_bw()
#> Error in bar_obj + theme_bw() : non-numeric argument to binary operator
#> In addition: Warning message:
#> Incompatible methods ("+.bar", "+.gg") for "+"
Real life situation
-
To get around this in
GGally
, I overwrite the+.gg
method. Unfortunately, this produces a warning and does not dispatch to the next available plus method.
I am open to other options, but I don't know how to produce one that would play well with other packages. -
I would like to be able to add a scale to a
ggmatrix
object in appropriate places only (Ex:ggmatrix_obj + gg_scale_obj
). With the current methods, I don't know how I can do this cleanly.
Goal
Define a generic add method (ex: add_gg(e1, e2)
). This generic add method should be called within +.gg
to avoid double dispatch confusion involving +
.
ggplot2
's +.gg
is not commutative. So I believe this situation has merit.
Using the implementation in #3818 , I would be able to define how a theme object is added to a custom object.
library(ggplot2)
x <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
foo_obj <- structure(
list(x, x),
class = c("foo", "gg")
)
`add_gg.foo` <- function(e1, e2) {
# only add to second plot
e1[[2]] <- e1[[2]] + e2
e1
}
print.foo <- function(x, ...) {
gridExtra::grid.arrange(x[[1]], x[[2]], ncol = 2)
}
foo_obj + theme_bw()
Created on 2020-02-11 by the reprex package (v0.3.0)