当也在另一个包中设置时,S4 方法失败
S4 method fails when also set in another package
当我尝试设置一个也在另一个包中定义的方法时,我遇到了一个奇怪的问题。可以找到演示此问题的示例包 here。
关键是我尝试设置的typeof
方法。我对 typeof
使用 setMethod
函数,当我构建包并在普通 S4 class.
上试用它时它可以工作
x <- new("A", x = 2)
typeof(x)
[1] "typeof was called"
[1] "myClassA"
但是,如果我在加载 s4test
包之前加载另一个先前也设置了 typeof
的包(例如 bigmemory),如果直接调用它,它会继续正常工作。
library(bigmemory)
library(s4test)
x <- new("A", x = 2)
typeof(x)
[1] "typeof was called"
[1] "myClassA"
但是,如果 typeof
方法被另一个方法内部调用(例如 nrow
参见 here),那么它将失败并且只有 returns 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"
问题是 Depends
并不总是确定的。 Imports
比使用 Depends
更安全,您可以阅读更多有关此内容的信息 here。
在全局环境中,您的包裹正在使用 bigmemory::typeof,并且在 nrow base::typeof.
内
> base::typeof(x)
[1] "S4"
> bigmemory::typeof(x)
[1] "typeof was called"
[1] "myClassA"
您可以通过直接引用您要使用的包名称的函数来解决这个问题。
胡安·安东尼奥走在正确的轨道上,
但它与 Depends
和 Imports
.
无关
答案在 Methods_for_Nongenerics
的文档条目中
(适用于 typeof
,因为它不是 base
中的通用函数):
In writing methods for an R package, it's common for these methods to apply to a function (in another package) that is not generic in that package; that is, there are no formal methods for the function in its own package, although it may have S3 methods. The programming in this case involves one extra step, to call setGeneric() to declare that the function is generic in your package.
Calls to the function in your package will then use all methods defined there or in any other loaded package that creates the same generic function. Similarly, calls to the function in those packages will use your methods.
The original version, however, remains non-generic. Calls in that package or in other packages that use that version will not dispatch your methods except for special circumstances...
您可以在干净的 R 会话中通过 运行 以下内容查看此效果:
environment(typeof)
<environment: namespace:base>
library(s4test)
environment(typeof)
<environment: 0x0000000017ca5e58>
加载包后,
typeof
函数已被通用化,
但不在其原始环境中。
也可以看到新泛型的环境的enclosing环境:
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"
当我尝试设置一个也在另一个包中定义的方法时,我遇到了一个奇怪的问题。可以找到演示此问题的示例包 here。
关键是我尝试设置的typeof
方法。我对 typeof
使用 setMethod
函数,当我构建包并在普通 S4 class.
x <- new("A", x = 2)
typeof(x)
[1] "typeof was called"
[1] "myClassA"
但是,如果我在加载 s4test
包之前加载另一个先前也设置了 typeof
的包(例如 bigmemory),如果直接调用它,它会继续正常工作。
library(bigmemory)
library(s4test)
x <- new("A", x = 2)
typeof(x)
[1] "typeof was called"
[1] "myClassA"
但是,如果 typeof
方法被另一个方法内部调用(例如 nrow
参见 here),那么它将失败并且只有 returns 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"
问题是 Depends
并不总是确定的。 Imports
比使用 Depends
更安全,您可以阅读更多有关此内容的信息 here。
在全局环境中,您的包裹正在使用 bigmemory::typeof,并且在 nrow base::typeof.
内> base::typeof(x)
[1] "S4"
> bigmemory::typeof(x)
[1] "typeof was called"
[1] "myClassA"
您可以通过直接引用您要使用的包名称的函数来解决这个问题。
胡安·安东尼奥走在正确的轨道上,
但它与 Depends
和 Imports
.
答案在 Methods_for_Nongenerics
的文档条目中
(适用于 typeof
,因为它不是 base
中的通用函数):
In writing methods for an R package, it's common for these methods to apply to a function (in another package) that is not generic in that package; that is, there are no formal methods for the function in its own package, although it may have S3 methods. The programming in this case involves one extra step, to call setGeneric() to declare that the function is generic in your package.
Calls to the function in your package will then use all methods defined there or in any other loaded package that creates the same generic function. Similarly, calls to the function in those packages will use your methods.
The original version, however, remains non-generic. Calls in that package or in other packages that use that version will not dispatch your methods except for special circumstances...
您可以在干净的 R 会话中通过 运行 以下内容查看此效果:
environment(typeof)
<environment: namespace:base>
library(s4test)
environment(typeof)
<environment: 0x0000000017ca5e58>
加载包后,
typeof
函数已被通用化,
但不在其原始环境中。
也可以看到新泛型的环境的enclosing环境:
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"