2011-11-10 46 views
0

无论是在包中还是偶尔在基本R中,我有时都想为现有函数添加一点风味。大多数情况下,这是函数开始或结束时发生的细微变化(愚蠢的例子:我希望cat函数在默认情况下在最后包含换行符)。覆盖方法使用原始实现来扩展它

现在我知道我可以简单地通过将我的新实现分配给它的名称来覆盖现有的方法,但是:那么,我仍然可以使用旧的方法吗?在cat的情况下,我会做这样的事情:

cat<-function(... , file = "", sep = " ", fill = FALSE, labels = NULL, 
    append = FALSE) 
{ 
    cat(..., "\n" , file = file, sep = sep, fill = fill, labels = labels, 
    append = append) 
} 

这意味着使用“旧” cat在新的实施。现在,如果我理解R中的调用和后期绑定的任何操作,这将会失败(无限递归)。

那么,有没有实现这一点(在功能的面向对象覆盖的精神)的一种方式,而不是诉诸

  • 给我的新功能的另一个名字(我希望它“只是工作”)
  • 下其他名称(然后,当我创建 这个功能在另一个R对话,我会忘记额外的步骤)
  • 使用原函数的所有源(如@Andrie说保存旧功能:重要的是要有最优雅的解决方案)

有没有这方面的范例?或者我怎么能以最安全的方式解决这个问题?或者我只是想太多?

编辑鉴于@ Andrie的回答:这可以做得很简单。然而,如果我想改变程序包中另一个函数调用的程序包中的某些函数的行为,Andrie的技巧将不起作用。

举个例子:我已经对glmnet包的绘图功能进行了大量的补充。但是如果你看看plot.cv.glmnet之类的东西,你会看到他们将该调用转发给该包中的另一个函数,所以我真的需要将新版本注入到包中(顺便说一句,可以用reassignInPackage)。但是当然,命名空间前缀将会失败,因为我刚刚替换了命名空间版本。这个例子并不像看起来那么人为:我去过那里好几次了。另一方面,也许有人会/可以争辩说,我应该放弃我的要求,在这种情况下?这将是最好的方式去呢?

回答

7

如果我理解正确,我认为这是一个简单的问题,指的是namespace::function,即在这种情况下,在您的函数中使用base::cat

例如:

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 
+0

<拍打前额/>。对于显而易见的(像往常一样,从我的角度来看)的观察(通常来自你的部分)。无论哪种方式,我都会提高一点(请参阅我的编辑几分钟)。 –