I have a generic function called foo
. It operates differently on the classes bar
and baz
but there is some shared pre-processing that need
1) Layer foo on top of actual generic Change foo
to perform the preliminary code and invoke foo_
a new generic as shown. Rename foo.bar
and foo.baz
to foo_.bar
and foo_.baz
respectively so that we are left with (have also added newlines to the example):
foo <- function(x) {
x <- x * 10
foo_(x)
}
foo_ <- function(x) UseMethod("foo_")
foo_.bar <- function(x) cat("Foo!", x, "\n")
foo_.baz <- function(x) cat("Baz!", x, "\n")
Now test it out:
a <- structure(1:5, class="bar")
b <- structure(6:10, class="baz")
foo(a)
## Foo! 10 20 30 40 50
foo(b)
## Baz! 60 70 80 90 100
For an example of this in a widely used package see the source of dplyr::mutate
2) NextMethod Another way would be to give every object a class vector of two classes with "foo"
made a subclass of "bar"
in the case of a
and of "baz"
in the case of b
. Then use NextMethod
. Solution (1) seems simpler and it may seem weird that "foo"
is a subclass of both "bar"
and "baz"
but here is an example of this one just in case:
foo <- function(x) UseMethod("foo")
foo.foo <- function(x) {
x <- x * 10
NextMethod()
}
foo.bar <- function(x) cat("Foo!", x, "\n")
foo.baz <- function(x) cat("Baz!", x, "\n")
Test it noting that we have changed the definitions of a
and b
so that they work with this approach:
a <- structure(1:5, class= c("foo", "bar"))
b <- structure(6:10, class = c("foo", "baz"))
foo(a)
## Foo! 10 20 30 40 50
foo(b)
## Baz! 60 70 80 90 100