谜题是访问对象的“伪插槽”中的列表元素。
使用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对象编写访问器。)我只想了解。
答案 0 :(得分:2)
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
答案 1 :(得分:0)
啊,马丁,你的回答让我得到了一些令我惊讶的发现!谢谢。指着我查看实例的attributes
是关键。我错过了那个段落?Classes。
以下显示names
插槽中列表的.Data
属性转移到实例本身:
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
属性!但为什么不转移所有其他属性?