我遇到了一些麻烦,它们以完全类型化的方式定义数组类(就R中的情况而言)。
我的例子:我想定义一个类Avector
,它应该包含类A
的任意数量的元素。
# Define the base class
setClass("A", representation(x = "numeric"))
# Some magic needed ????
setClass("Avector", ???)
# In the end one should be able to use it as follows:
a1 <- new("A", x = 1)
a2 <- new("A", x = 2)
X <- new("Avector", c(a1, a2))
我知道在R中不可能有一个对象向量。所以我猜它会被存储在一种&#34; typed&#34;名单。 我找到了一些解决方案,但我对此并不满意:
# Define the vectorized class
setClass(
"Avector",
representation(X = "list"),
valididty = function(.Object)) {
if (all(sapply(.Object@X, function(x) class(x) == "A")))
TRUE
else
"'Avector' must be a list of elements in the class 'A'"
}
)
# Define a method to subscript the elements inside of the vector
setMethod(
"[", signature(x = "Avector", i = "ANY", j = "ANY"),
function(x, i, j, ...) x@X[[i]]
)
# Test the class
a1 <- new("A", x = 1)
a2 <- new("A", x = 2)
avec <- new("Avector", X = list(a1, a2))
# Retrieve the element in index i
avec[i]
这种方法对我来说更像是黑客攻击。有没有办法在R中以规范的方式执行此操作而不用手工执行此类型检查和索引方法?
修改:
如果类A
不是由原子槽组成,那么这也应该成立。例如,在以下情况下:
setClass("A", representation(x = "data.frame"))
我很乐意帮忙:) 干杯, 阿德里安
答案 0 :(得分:1)
答案在某种程度上取决于您要完成的任务,并且在您的使用案例中可能会或可能不会。 S4的工作方式是对象应该是高级的,以避免过多的开销。
通常,插槽必须是矢量。您无法在R中定义新的原子类型。因此,在您的玩具示例中,而不是调用
avec <- new("Avector", X = list(a1, a2))
你打电话
avec <- new("A", x = c(1, 2))
例如,这可能需要其他插槽(以前是矢量)成为阵列。
如果您迫切希望拥有原子类型,那么您可以覆盖其中一种现有类型。我认为bit64包就是这样做的。基本上你要做的是创建一个继承自numeric
的新类,然后编写许多方法来取代所有新类的默认方法。