当我尝试设置在另一个包中定义的方法时,我遇到了一个奇怪的问题。可以找到here来演示此问题的示例程序包。
关键是我尝试设置的typeof
方法。我将setMethod
函数用于typeof
,并且在构建软件包并在普通的S4类上尝试时可以使用。
x <- new("A", x = 2)
typeof(x)
[1] "typeof was called"
[1] "myClassA"
但是,如果在加载typeof
包之前加载另一个先前也设置了s4test
的包(例如bigmemory),则直接调用它仍可以正常工作。
library(bigmemory)
library(s4test)
x <- new("A", x = 2)
typeof(x)
[1] "typeof was called"
[1] "myClassA"
但是,如果typeof
方法是由另一种方法在内部调用的(例如nrow
参见here),则它将失败,并且仅返回S4
nrow(x)
[1] "A"
attr(,"package")
[1] "s4test"
Function: typeof (package base)
x="ANY"
x="big.matrix"
x="myClass"
A connection with
description "stdout"
class "terminal"
mode "w"
text "text"
opened "opened"
can read "no"
can write "yes"
[1] "S4"
答案 0 :(得分:2)
胡安·安东尼奥走在正确的轨道上,
但这与Depends
和Imports
无关。
答案在Methods_for_Nongenerics
的文档条目中
(这适用于typeof
,因为它不是base
中的通用函数):
在为R包编写方法时,通常将这些方法应用于该包中不通用的函数(在另一个包中);也就是说,尽管它可能具有S3方法,但在其自己的程序包中没有用于该功能的形式方法。在这种情况下,编程涉及一个额外的步骤,即调用setGeneric()来声明该函数在您的程序包中是通用的。
然后,对包中的函数的调用将使用在此包中定义的所有方法,或使用任何其他已加载的创建相同泛型函数的包中的方法。同样,在这些包中调用该函数将使用您的方法。
但是,原始版本仍然是非通用的。除非有特殊情况,否则该软件包或使用该版本的其他软件包中的调用将不调度您的方法...
您可以通过在干净的R会话中运行以下命令来查看此操作的效果:
environment(typeof)
<environment: namespace:base>
library(s4test)
environment(typeof)
<environment: 0x0000000017ca5e58>
加载软件包后,
typeof
函数已成为通用函数,
但不在其原始环境中。
您还可以看到新泛型环境的封闭环境:
parent.env(environment(typeof))
<environment: namespace:base>
在调用函数时,
R首先看一下当前环境,
并在找不到任何东西的情况下查看封闭环境。
nrow
函数是base
包的一部分
(它也不是通用的,
虽然在这里不相关),
这意味着它将在看到通用typeof
之前找到自己的非通用Methods_for_Nongenerics
。
setMethod('nrow', signature(x="myClass"),
function(x) {
# find the generic version from the global environment and bind it here
typeof <- get("typeof", .GlobalEnv)
switch(typeof(x),
"myClassA" = "A rows",
"myClassB" = "B rows")
}
)
nrow(x)
[1] "typeof was called"
[1] "A rows"
的文档介绍了不同的情况,
但就您而言
您实际上可以执行以下操作:
<button class="subform add" onclick="addSubform(stuff); return false;" ...></button>
答案 1 :(得分:0)
问题是Depends
并不总是确定的。 Imports
比使用Depends
更安全,您可以详细了解here。
在全球环境中,您的软件包使用bigmemory :: typeof,并在nrow base :: typeof内部使用。
> base::typeof(x)
[1] "S4"
> bigmemory::typeof(x)
[1] "typeof was called"
[1] "myClassA"
您可以通过直接引用要使用的软件包名称的函数来解决此问题。