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