问题
Whether in a package or occasionally in base R, I sometimes want to add a little flavor to an existing function. Most of the times, this is a minor change of what should happen at the start or at the end of the function (silly example: I'd like the cat
function to include a newline at the end by default).
Now I know I can simply overwrite an existing method by assigning my new implementation to its name, BUT: how, then, can I still use the old one? In the case of cat
, I would have to do something like:
cat<-function(... , file = "", sep = " ", fill = FALSE, labels = NULL,
append = FALSE)
{
cat(..., "\n" , file = file, sep = sep, fill = fill, labels = labels,
append = append)
}
This means using the 'old' cat
in the implementation of the new one. Now if I understand anything about how calling and late binding in R work, this will simply fail (infinite recursion).
So is there a way of achieving this (in the spirit of object-oriented overrides of functions), without resorting to
- giving my new function another name (I want it to 'just work')
- saving the old function under some other name (Then, when I create this function in another R session, I might forget the extra step)
- using all the source of the original function (As @Andrie said: it is important to have the most elegant solution possible)
Is there a paradigm for this? Or how could I go about this in the safest way possible? Or am I just wishing for too much?
Edit Given @Andrie's answer: this can be done quite simply. However, Andrie's trick will not work if I want to alter the behaviour of some function in a package that is called by another function in the package.
As an example: I have made numerous additions to the plotting functions of the glmnet
package. But if you look at plot.cv.glmnet
and the likes, you will see that they forward the call to another function within that package, so I'd really need to inject my new version into the package (which, by the way, can be done with reassignInPackage
). But then of course the namespace prefixing will fail because I've just replaced the namespaced version. This example is not as contrived as it might seem: I've been there quite a few times. On the other hand, maybe somebody will/can argue that I should drop my requirements in that case? Which would be the best way to go then?
回答1:
If I understand you correctly, I think it's a simple matter of referring to namespace::function
, i.e. in this case use base::cat
inside your function.
For example:
cat <- function(... , file = "", sep = " ", fill = FALSE, labels = NULL,
append = FALSE)
{
base::cat(..., "\n" , file = file, sep = sep, fill = fill, labels = labels,
append = append)
}
> cat("Hello", "world!")
Hello world!
> cat("Text on line 2")
Text on line 2
来源:https://stackoverflow.com/questions/8077003/overwrite-method-to-extend-it-using-the-original-implementation