如何为自定义S3类实现提取/子设置([,[<-,[[,[[<-)函数?

时间:2018-11-08 12:13:39

标签: r oop

我有一个自定义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,则头和尾都应该工作)。

我对此的问题分为三个部分:

  1. 为S3类实现自定义访问器功能的最佳方法是什么?我可以依靠基础原始类吗?
  2. 我需要哪种访问器功能?我认为我不需要定义[[[<-[[<-$,因为在这些情况下,list的继承功能对于{ {1}}。我还是应该实施它们吗?
  3. 如何实现带有3个参数(如foo_list[<-的运算符?您需要对象,索引和新值吗?

以下[[<-的代码似乎有效:

[

另一方面,这不是:

`[.foo_list` <- function(x, i) {
  class(x) <- "list"
  as.foo_list(x[i])
}

如何解决此问题(1 / .3),甚至必须修复(2。)?

1 个答案:

答案 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运算符,以下更简单的实现有效:

[