这是一个单线程,它可以做到这一点。这里的PackageFuncA
是stats::acf
和PackageFuncB
是我们想用my.plot.acf
替换的stats:::plot.acf
。 my.plot.acf
打印"Hello"
然后调用真实的stats:::plot.acf
。
# we want this to run in place of stats:::plot.acf
my.plot.acf <- function(x, ...) { cat("Hello\n"); stats:::plot.acf(x, ...) }
# this does it
library(proto)
acf <- with(proto(environment(acf), acf = stats::acf, plot.acf = my.plot.acf), acf)
# test
acf(1:10)
甲原对象是这样的环境,其经由proto
功能插入到对象的任何功能都有它的环境自动地复位到该对象。 proto()
的第一个参数是原始对象的父项。
在上面的例子中,它的设置使得acf
变量引用插入到proto对象中的版本acf
(除了原来的对象被修改为原始对象之外,它与原始对象相同)。当运行新的acf
函数时plot.acf
是一个自由变量(即,未在acf
中定义),因此它在acf
的父级中查找,并且它是原始对象中的环境,它在其中找到新的plot.acf
。 acf
可能有其他自由变量,但在这些情况下,因为它们在原始对象中未找到,它将查看原始对象的父级,原始对象是原始的acf
的原始环境。在图方面,我们有这个地方<-
意味着左侧是右侧的父:
environment(stats::acf) <- proto object <- revised acf
与原对象既包含plot.acf
和修订后的acf
。
我们还将新的plot.acf
的环境设置为原始对象。我们可能需要也可能不需要这样做。在很多情况下,这并不重要。如果它是重要的是不要设置新plot.acf
那就这样做的环境,因为原不落的插入功能使用[[...]]
环境:
acf <- with(p <- proto(environment(acf), acf = stats::acf), acf)
p[["plot.acf"]] <- my.plot.acf
在这个例子中,这两种方法的工作。
这将有可能做这一切与平原环境下,在不必使用几行代码的代价:
# create new environment whose parent is the original acf's parent
e <- new.env(parent = environment(stats::acf))
# the next statement is only need to overwrite any acf you already might have from
# trying other code. If you were sure there was no revised acf already defined
# then the next line could be omitted. Its a bit safer to include it.
acf <- stats::acf
# This sets the environment of the new acf. If there were no acf already here
# then it would copy it from stats::acf .
environment(acf) <- e
# may or may not need next statement. In this case it doesn't matter.
environment(my.plot.acf) <- e
e$plot.acf <- my.plot.acf
acf(1:10)
在这种情况下,我们没有下过修订acf
在e
作为原例如,但只设置其父。事实上,将修订的acf
纳入e
或原始对象并非绝对必要,但仅在原始案例中完成,因为原型具有重置环境的副作用,并且是我们之后的副作用。另一方面,有必要将修改后的plot.acf
放在e
或原始对象中,以便在原始对象之前遇到它。
您可能想要阅读此paper,特别是第21页开始的代理部分,因为此处显示的技术是代理对象的示例。
创建自己的PackageFunA并更改对PackageFunB的调用以便它调用您的函数会更容易吗? – joran
请参阅'?assignInNamespace' – Andrie
joran - 我宁愿不维护自己的PackageFuncA版本,特别是因为它不仅仅是几行代码。 – SFun28