在R6类

时间:2018-06-13 16:37:55

标签: r r6

这是不起作用的:

library(R6)

Foo = R6::R6Class(
    'Foo',
    public = list(
        X = NULL,
        metadata = NULL,
        initialize = function(X, metadata){
            self$X = X
            self$metadata = metadata
        },
        `[` = function(selection){
            subfoo = Foo$new(X = X[selection], 
                             metadata = self$metadata)
            return(subfoo)
        }
    )
)

具体来说,[方法是垃圾:

> X = matrix(1:8, ncol = 2)
> foo = Foo$new(X, 'blah blah')
> foo[1:2,]
Error in foo[1:2, ] : object of type 'environment' is not subsettable

期望的结果是foo[1:2,]将成为Foo类的对象,就像foo一样,只是它的矩阵foo$X更小。有没有直接的方法来实现这个将[运算符直接暴露给用户?

2 个答案:

答案 0 :(得分:1)

答案比我想的要晚。问题是您正在注册可以像这样调用的方法

Column

您想要的地方

x$`[`(1:3)

以下内容将为所有R6对象正确地调度所有x[1:3] [调用(通过S3)。

[<-

请注意,对于`[.R6` <- function(x, ...) x$`[`(...) `[<-.R6` <- function(x, ...) x$`[<-`(...) 方法,您不应执行任何此类操作,因为R6对象是环境,因此这些方法已被定义和使用。

理想情况下,如果也可以重写[[以便我们可以创建函子对象(例如调用(),那将是很好的选择,但我不知道该怎么做。 >

答案 1 :(得分:0)

如果其他人也正在寻找它,下面是一个完整的工作示例(基于Ian Fellows' answer):

library(R6)

Foo = R6::R6Class(
  'Foo',
  public = list(
    x = NULL,
    initialize = function(x) {
      self$x = x
    },
    
    `[` = function(idx) {
      self$x[idx]
    },
    
    `[<-` = function(idx, value) {
      self$x[idx] <- value
      invisible(self)  # important!
    },
    
    length = function() {
      length(self$x)
    }
  )
)

# set up method dispatch
`[.Foo`    <- function(obj, ...) obj$`[`(...) 
`[<-.Foo`  <- function(obj, ...) obj$`[<-`(...) 
length.Foo <- function(obj, ...) obj$length(...)

# test
foo <- Foo$new(c(1,2,3))
(n <- length(foo))
#> [1] 3
foo[1:n]
#> [1] 1 2 3
foo[2] <- 0
foo[1:n]
#> [1] 1 0 3

reprex package(v0.3.0)于2020-10-09创建

(如果需要,返回值可以是另一个Foo对象。为简单起见,我将返回一个向量)