R参考类中的非标准设置函数

时间:2019-01-15 20:56:14

标签: r reference-class

是否可以获取语法

foo$bar(x) <- value

foo是引用类对象而bar是方法的地方工作吗? 即引用类中的方法是否可以进行“子集分配”并具有“替换功能”?

其他OO系统是否可以使用这种语法?

示例: 我将用一个虚构的用例进行说明。想象一下一个参考类Person,其中包含一个人的一些基本信息。特别是,一个名为fullname的字段就是一个名为list的字段:

PersonRCGen <- setRefClass("Person",
                           fields = list(
                             fullname = "list",
                             gender = "character"
                           ))

接下来,我们应该定义一些方法来获取和设置fullnames列表中的特定名称,这些名称(尝试)可以提供上述语法/接口。到目前为止,我最好的尝试是:

PersonRCGen$methods(
  name = function(x) { # x is the dataset,
    .self$fullname[[x]]
  },
  `name<-` = function(x, value) {
    .self$fullname[[x]] <- value
  }
)

这里的命名还应该说明我正在尝试做的事情。

我们初始化一个新对象:

a_person <- PersonRCGen$new(fullname = list(first = "Jane", last = "Doe"),
                            gender = "F")

直接访问fullname字段并通过定义的get函数访问名字和姓氏可以按预期工作:

a_person$fullname
#$`first`
#[1] "Jane"
# 
#$last
#[1] "Doe"

a_person$name("first")
#[1] "Jane"

a_person$name("last")
#[1] "Doe"

但是,为了在fullname列表中设置特定名称,我希望使用以下语法/接口,但不幸的是失败。

a_person$name("first") <- "Jessie"
#Error in a_person$name("first") <- "Jessie" : 
#  target of assignment expands to non-language object

我知道以下工作(基本上使该方法的命名不佳)。

a_person$`name<-`("first", "Johnny")
a_person$fullname
#$`first`
#[1] "Johnny"
#
#$last
#[1] "Doe"

在我的实际用例中,我想避免get和set函数使用“传统的” getName(x)setName(x, value)名称。

2 个答案:

答案 0 :(得分:3)

我可能会误解您想要达到的目标,但这有什么问题呢?

person = setRefClass("Person",
                     fields = list(
                       fullname = "list",
                       gender = "character"
                     ))

a_person = person$new(fullname = list(first = "James", last = "Brown"), gender="M")

a_person$fullname$first = "Bob"

a_person

Reference class object of class "Person"
Field "fullname":
$`first`
[1] "Bob"

$last
[1] "Brown"

Field "gender":
[1] "M"

答案 1 :(得分:3)

我认为您无法使用所需的语法来做到这一点。

请注意,如果您执行类似的分配,例如

,您将得到相同的错误。
a_person$hello("first") <- "John"

所以这确实是一个基本问题。

起作用的是以下语法:

name(a_person, "first") <- "John"

然后您总共可以得到如下内容:

PersonRCGen <- setRefClass("Person",
                  fields = list(
                    fullname = "list",
                    gender = "character"
                  ),
                  methods = list(
                    initialize = function(...) {
                      initFields(...)
                    },
                    name = function(x) {
                      .self$fullname[[x]]
                    }
                  )
)

setGeneric("name<-", function(x, y, value) standardGeneric("name<-"))
setMethod("name<-", sig = "ANY", function(x, y, value) {
  UseMethod("name<-")
})
# some extras
"name<-.default" <- function(x, y, value) {
  stop(paste("name assignment (name<-) method not defined for class", class(x)))
}
"name<-.list" <- function(x, y, value) {
  x[[y]] <- value
  return(x)
}
# and here specifically
"name<-.Person" <- function(x, y, value) {
  x$fullname[[y]] <- value
  return(x)
}

# example to make use of the above
a_person <- PersonRCGen$new(
  fullname = list(
    first = "Jane",
    last = "Doe"
  ),
  gender = "F"
)

a_person$name("first")
#> [1] "Jane"
name(a_person, "middle") <- "X."
a_person$name("middle")
#> [1] "X."

我知道这并非您真正想要的,但希望对您有所帮助。

相关问题