【问题标题】:Call more then one slot or fields in S4 or Reference Classes在 S4 或参考类中调用多个插槽或字段
【发布时间】:2013-09-05 12:40:21
【问题描述】:

是否可以调用或设置多个插槽的值?

A<-setClass(Class="A",slot=c(name="character",type="character"))
a<-A()
slot(object,c("name","type"),check=T)

我必须编写自己的 getSlot 和 setSlot 方法吗?在 R5 中如何实现?

AB <- setRefClass("AB", fields=c(name="character"),
                  methods=list(getName=AB.getName)
                  )

AB.getName<-function(object){
  object$name
}

a<-AB(name="abc")
AB.getName(a)

【问题讨论】:

标签: r s4 reference-class


【解决方案1】:

此答案适用于参考类。

让我们从AB的最简单定义开始,没有任何方法。

AB <- setRefClass(
  "AB", 
  fields = list(
    name = "character"
  )
)

您可以像检索列表一样检索name 字段的值。

ab <- AB$new(name = "ABC")
ab$name
## [1] "ABC"
(ab$name <- "ABCD")
## [1] "ABCD"

可以自动生成访问器方法来获取和设置名称字段。

AB$accessors("name")
ab$getName()
ab$setName("ABCDE")

这确实毫无意义,因为它的行为与以前完全相同,但输入更多。有用的是在设置字段时进行输入检查(或其他自定义行为)。为此,您可以添加自己编写的 setName 方法。

AB$methods(
  setName = function(x) 
  {
    if(length(x) > 1)
    {
      warning("Only using the first string.")
      x <- x[1]
    }
    name <<- x
  }
)
ab$setName(letters)
## Warning message:
## In ab$setName(letters) : Only using the first string.

也可以在分配引用类模板时定义此方法(通常更有用)。

AB <- setRefClass(
  "AB", 
  fields = list(
    name = "character"
  ), 
  methods = list(
    setName = function(x) 
    {
      if(length(x) > 1)
      {
        warning("Only using the first string.")
        x <- x[1]
      }
      name <<- x
    }
  )
)

对评论的回应:

可以,但是:

getFieldNames 如果实现为names(AB$fields()),则更易于维护。

setRefClass 中定义字段时,请使用列表。例如,list(name="character", var2="character")

分配引用类的实例时,使用new。例如AB$new(name="abc",var2="abc")

【讨论】:

  • 所以我必须遵循这个原则? 'AB.getFields
  • 非常感谢您的帮助。要查找有关它的信息,比在 Java、PHP 或其他一些通用语言中查找要困难得多。
  • @Klaus 目前对参考类的帮助非常有限。从 ?ReferenceClasses 帮助页面和我的书的第 16 章开始,学习 R。:) shop.oreilly.com/product/0636920028352.do
【解决方案2】:

在S4中,默认initialize方法允许写

A <- setClass(Class="A", slot=c(name="character",type="character"))
a <- A(name="abc", type="def")
initialize(a, name="cde", type="fgh")

必须编写您自己的初始化方法(如果有 - I think 通常最好避免使用它们)以允许这种使用。没有将 S4 表示转换为列表的默认方法。

您可以将这些想法合并到您自己的泛型/方法中,例如

setGeneric("values", function(x, ...) standardGeneric("values"))
setMethod("values", "A", function(x, ...) {
    slts = slotNames(x)
    lapply(setNames(slts, slts), slot, object=x)
})

setGeneric("values<-", function(x, ..., value) standardGeneric("values<-"))
setReplaceMethod("values", c(x="A", value="list"), function(x, ..., value) {
    do.call("initialize", c(x, value))
})

> a <- A(name="abc", type="def")
> values(a)  = list(name="cde", type="fgh")
> values(a)
$name
[1] "cde"

$type
[1] "fgh"

【讨论】:

  • 谢谢,这就是我建议没有矢量化函数的原因。
  • @Klaus:您可能想查看格中的modifyList 函数,了解有关“有针对性”修改递归结构的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-11
  • 2013-03-09
  • 2012-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多