难题是访问对象“伪槽”中列表的元素。
使用可以尝试的 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"
但是伪槽中没有名字。
[email protected]
## [[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 对象编写访问器。)我只是想理解。
S4 将槽实现为属性,而 R 将列表元素的名称存储为列表上的属性。因此存在冲突,如
?Classes
中提到的。 “解决方案”是创建一个带有“名称”插槽的类
A = setClass("A", representation("list", names="character"))
但这也需要对名称进行显式管理,例如
setMethod("[", c("A", "ANY", "missing", "missing"),
function(x, i, j, ..., drop=TRUE)
{
initialize(x, [email protected][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
啊,马丁,你的回答让我有了一些让我惊讶的发现!谢谢。引导我查看实例的
attributes
是关键。我错过了“课程”中的那一段。
如下所示,
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([email protected])
## NULL
嗯,不是所有属性。上面原始问题中对象
B2
的结果表明,如果 .Data
项本身就是一个实例,则其属性不会传输到包含实例。
这仍然是一个悬而未决的问题。当然你不想转移
$class
属性!但为什么不转移所有其他属性呢?
我想我对你的问题有一个解决方案,线索是正确设置孩子的
contains
。父“A”类必须是第一个,并且必须重复该列表。或者,可以使用namedList,然后不需要重复。
setClass(
"A",
contains = "list"
)
setClass(
"B",
contains = c("A", "list")
)
obj <- new("A", list(t = 2))
obj2 <- new("B", list(t = 3))
obj[["t"]]
# 2
obj2[["t"]]
# 3
is(obj, "list")
# TRUE
is(obj2, "A")
# TRUE
is(obj2, "list")
# TRUE
setClass(
"C",
contains = "list"
)
setClass(
"D",
contains = c("C", "list")
)
obj <- new("C", list(t = 2))
obj2 <- new("D", list(t = 3))
obj[["t"]]
# 2
obj2[["t"]]
# 3
is(obj, "list")
# TRUE
is(obj2, "C")
# TRUE
is(obj2, "list")
# TRUE