【问题标题】:subclassing S4 class that contains a list with names: access by name包含名称列表的 S4 类的子类化:按名称访问
【发布时间】:2014-05-21 15:48:12
【问题描述】:

谜题是访问对象“伪槽”中的列表元素。

使用可能尝试的 4 种方法中的 2 种是成功的:

setClass("TempA", contains="list")
A = new("TempA", list(a=1,b=2))
A   

仅打印 A 不会显示列表名称。

## An object of class "TempA"
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 2

不过,您可以按名称提取元素。

A[["b"]]  
## [1] 2

并且 names() 提取名称。

names(A) 
## [1] "a" "b"

但是伪插槽中没有名称。

A@.Data  
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 2

那么,如果不在伪插槽本身中,名称隐藏在哪里?

情节变厚了。我的目标是子类化(添加一些插槽;此处未显示)。 但是如果我们进行子类化,即使上面的两种成功的方法现在也失败了。该列表的名称显然不存在。

setClass("TempB", contains="TempA")
B = new("TempB", list(a=1,b=2))
names(B) ## no names.
## NULL
B[["b"]] ## NULL
## NULL

这是一种不同的方法。这行吗?没有。

B2 = new("TempB", new("TempA", list(a=1,b=2)))
B2[["a"]]  # NULL
## NULL
names(B2) # NULL
## NULL
names(as(B2, "TempA"))  ## still no dice
## NULL

总之,当伪槽是一个命名列表时,尝试查看或使用这些名称只有 4 种明显方法中的 2 种是成功的,而在子类化后 4 种方法中则为零。解决问题不是问题;这很容易。 (虽然我想知道如何使用名称为 TempB 对象编写访问器。)我只是想了解。

【问题讨论】:

    标签: r s4 slot


    【解决方案1】:

    S4 将槽实现为属性,而 R 将列表元素的名称作为属性存储在列表中。因此存在冲突,在?Classes 中提到。 “解决方案”是创建一个带有“名称”插槽的类

    A = setClass("A", representation("list", names="character"))
    

    但这也需要对名称进行显式管理,例如,

    setMethod("[", c("A", "ANY", "missing", "missing"),
        function(x, i, j, ..., drop=TRUE)
    {
        initialize(x, x@.Data[i], names=names(x)[i], ...)
    })
    

    导致

    > a = A(list(a=1, b=2))
    > a[2:1]
    An object of class "A"
    [[1]]
    [1] 2
    
    [[2]]
    [1] 1
    
    Slot "names":
    [1] "b" "a"
    

    但也明显不完整

    > a[20]
    An object of class "A"
    [[1]]
    NULL
    
    Slot "names":
    [1] NA
    

    【讨论】:

      【解决方案2】:

      啊,马丁,你的回答让我有了一些令我惊讶的发现!谢谢你。指向我查看实例的attributes 是关键。我错过了 ?Classes 中的那一段。

      下图显示.Data槽中列表的names属性转移到实例本身:

      attributes(A)$names
      ## [1] "a" "b"
      

      那么,是否所有属性都从.Data 槽移动到实例?确实是的!

      tempList = list(a=3, b=4)
      attributes(tempList)$dummy = "dummy"
      E = new("TempA", tempList)
      attributes(E)$names
      ## $names
      ## [1] "a" "b"
      ## 
      attributes(E)$dummy
      ## $dummy
      ## [1] "dummy"
      attributes(E@.Data)
      ## NULL 
      

      嗯,不是所有的属性。原始问题中对象B2 的结果表明,如果.Data 项目本身是一个实例,则其属性不会转移到包含实例。

      这仍然是一个悬而未决的问题。当然你不想转移$class 属性!但是为什么不转移所有其他属性呢?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-28
        • 1970-01-01
        • 2013-01-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多