我有一个自定义的S3类foo,它在常规的顶部添加了一些自定义行为data.frame:
foo_object <- data.frame()
class(foo_object) <- c("foo", "data.frame")
Run Code Online (Sandbox Code Playgroud)
对于此类,还应该有一个列表类foo_list来存储许多这些foo对象。
foo_list_object <- list()
class(foo_list_object) <- c("foo_list", "list")
Run Code Online (Sandbox Code Playgroud)
如果通过这样对列表上的多个元素应用子集操作,则foo_list_object[c(1,2,3)]只会得到class的对象list。但是我希望它保持不变foo_list。
Hadley 说,您应该为向量类实现自定义访问器函数,以实现此行为:
实现矢量类时,应实现以下方法:length,[,[<-,[[,[[<-,c。(如果[实现了rev,则头和尾都应该工作)。
我的问题包括三个部分:
[[,[<-,[[<-或者$因为在这些情况下的继承功能的list行为正确也foo_list。我还是应该实施它们吗?[<-或)的运算符[[<-?您需要对象,索引和新值吗?以下代码[似乎有效:
`[.foo_list` <- function(x, i) {
class(x) <- "list"
as.foo_list(x[i])
}
Run Code Online (Sandbox Code Playgroud)
另一方面,这不会:
`[[<-.foo_list` <- function(x, i, y) {
if (!is.foo(y)) {
stop("Please provide an object of class foo.")
}
x[[i]] <- y
}
Run Code Online (Sandbox Code Playgroud)
如何解决此问题(1 / .3),甚至必须修复(2.)?
为S3类实现自定义访问器功能的最佳方法是什么?我可以依靠基础原始类吗?
是的你可以。在中调用NextMethod,[<-.foo_list然后根据需要将结果包装在您的类中。
我是否仍应实施[所有访问器]?
如果希望它们的结果类型为foo_list或需要检查参数类型,则可以,您需要实现赋值访问器(但请参见下文)。你不会需要重写元素读存取([[,$),除非你想改变自己的语义:它们继承正确的行为list类。
如何实现带有3个参数(例如
[<-或)的运算符[[<-?
基本上就像您所做的那样。您只需要调整参数名称:新值参数需要命名,value因为R在内部使用命名参数调用函数。最后一行将导致无限递归-您需要unclass x先行使用或NextMethod:
`[[<-.foo_list` <- function(x, i, value) {
stopifnot(is.foo(value))
NextMethod()
}
Run Code Online (Sandbox Code Playgroud)
这有效,并保留的类类型x。请注意,实现此方法的唯一原因是在第一行中执行检查。如果不需要此检查,则根本不需要实现该方法。
同样,对于您的[操作员而言,以下更简单的实现也可以工作:
`[.foo_list` <- function(x, i) {
as.foo_list(NextMethod())
}
Run Code Online (Sandbox Code Playgroud)