子类化包含名称列表的 S4 类:按名称访问

问题描述 投票:0回答:3

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

使用可以尝试的 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 对象编写访问器。)我只是想理解。

r r-s4 slot
3个回答
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, [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

0
投票

啊,马丁,你的回答让我有了一些让我惊讶的发现!谢谢。引导我查看实例的

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
属性!但为什么不转移所有其他属性呢?


0
投票

我想我对你的问题有一个解决方案,线索是正确设置孩子的

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
© www.soinside.com 2019 - 2024. All rights reserved.