我想为我的类myClass
实现内部通用[<-
(〜help(Extract)
)的插入方法。
在通过[<-
将实际的 insetting 传递给NextMethod()
之前,此方法应该运行一堆测试。
我了解:
NextMethod()
调用通常不需要任何参数(尽管手动提供它们似乎也无济于事)。这是我的代表:
x <- c(1,2)
class(x) <- c("myClass", "numeric")
`[<-.myClass` <- function(x, i, j, value, foo = TRUE, ...) {
if (foo) {
stop("'foo' must be false!")
}
NextMethod()
}
x[1] <- 3 # this errors out with *expected* error message, so dispatch works
x[1, foo = FALSE] <- 3 # this fails with "incorrect number of subscripts
似乎正在发生的事情是,NextMethod()
也继续传递foo
到内部通用[<-
,该错误将foo
误认为另一个索引,并因此导致错误(因为在这种情况下,x
没有第二维可以索引)。
我还尝试提供明确没有提供NextMethod()
的参数,但这也失败了(请参见中断下方的reprex)。
如何避免在方法中添加其他参数而阻塞NextMethod()
?
(奖金:有人知道构建内部泛型方法的好资源吗?@Hadleys adv-r有点问题)。
使用显式参数表示:
x <- c(1,2)
class(x) <- c("myClass", "numeric")
`[<-.myClass` <- function(x, i = NULL, j = NULL, value, foo = TRUE, ...) {
if (foo) {
stop("'foo' must be false!")
}
NextMethod(generic = "`[<-`", object = x, i = i, j = j, value = value, ...)
}
x[1] <- 3 # this errors out with expected error message, so dispatch works
x[1, foo = FALSE] <- 3 # this fails with "incorrect number of subscripts
答案 0 :(得分:5)
除了剥离类(它复制了x
之外),我看不到其他简单的方法
`[<-.myClass` <- function(x, i, value, ..., foo = TRUE) {
if (foo) {
cat("hi!")
x
} else {
class_x <- class(x)
x <- unclass(x)
x[i] <- value
class(x) <- class_x
x
}
}
x <- structure(1:2, class = "myClass")
x[1] <- 3
#> hi!
x[1, foo = FALSE] <- 3
x
#> [1] 3 2
#> attr(,"class")
#> [1] "myClass"
这不是通用方法-仅[
,[<-
等需要,因为它们不使用常规规则进行参数匹配:
请注意,这些操作不以标准方式匹配其索引参数:参数名称被忽略,仅使用位置匹配。因此,
m[j = 2, i = 1]
等效于m[2, 1]
,而不等效于m[1, 2]
。
(摘自?`[`
中的“参数匹配”部分)
这意味着您的x[1, foo = FALSE]
等效于x[1, FALSE]
,然后您会收到一条错误消息,因为x
不是矩阵。
无效的方法:
为NextMethod()
提供附加参数:这只会增加参数数量,而不会减少
将foo
与rm(foo)
解除绑定:这会导致有关未定义的foo
的错误。
用丢失的符号替换foo
:这会导致错误,没有提供foo
,没有默认参数。
答案 1 :(得分:3)
这就是我的理解方式,但是我对这个主题了解不多,所以我希望我不要说太多错误的话。
来自?NextMethod
NextMethod调用下一个方法(由类向量确定, 提供给泛型的对象或第一个参数 如果调用了方法,则返回包含NextMethod的函数 直接)。
您的班级向量是:
x <- c(1,2)
class(x) <- "myClass" # note: you might want class(x) <- c("myClass", class(x))
class(x) # [1] "myClass"
因此,这里没有“下一个方法”,并且[<-.default
不存在。
如果我们定义它会发生什么?
`[<-.default` <- function(x, i, j, value, ...) {print("default"); value}
x[1, foo = FALSE] <- 3
# [1] "default"
x
# [1] 3
如果有一个带有...
参数的默认方法,它将像foo
参数一样正常工作,但事实并非如此,因此我认为不能调用NextMethod
照原样。
您可以执行以下操作来解决以下事实:所谓的东西都不喜欢被提供foo
参数:
`[<-.myClass` <- function(x, i, j, value, foo = FALSE, ...) {
if (foo) {
stop("'foo' must be false!")
}
`[<-.myClass` <- function(x, i, j, value, ...) NextMethod()
args <- as.list(match.call())[-1]
args <- args[names(args) %in% c("","x","i","j","value")]
do.call("[<-",args)
}
x[1, foo = FALSE] <- 3
x
# [1] 3 2
# attr(,"class")
# [1] "myClass"
另一个示例,其类更复杂:
library(data.table)
x <- as.data.table(iris[1:2,1:2])
class(x) <- c("myClass",class(x))
x[1, 2, foo = FALSE] <- 9999
# Sepal.Length Sepal.Width
# 1: 5.1 9999
# 2: 4.9 3
class(x)
# [1] "myClass" "data.table" "data.frame"
如果下一个方法具有除x
,i
,j
和value
之外的其他参数,则此方法将失败,在这种情况下,最好明确说明我们的其他参数和运行args <- args[! names(args) %in% c("foo","bar")]
。然后它可能会起作用(只要参数明确给出为match.call
不会捕获默认参数)。我无法对此进行测试,因为我不知道[<-
的这种方法。