如何定义S4类的子集运算符?

时间:2012-06-09 14:33:59

标签: oop r subset s4

我无法确定为S4类定义[$[[子集运算符的正确方法。

有人能为我提供一个为S4类定义这三个的基本示例吗?

2 个答案:

答案 0 :(得分:37)

发现通用,以便我们了解我们的目标

> getGeneric("[")
standardGeneric for "[" defined from package "base"

function (x, i, j, ..., drop = TRUE) 
standardGeneric("[", .Primitive("["))
<bytecode: 0x32e25c8>
<environment: 0x32d7a50>
Methods may be defined for arguments: x, i, j, drop
Use  showMethods("[")  for currently available ones.

定义一个简单的类

setClass("A", representation=representation(slt="numeric"))

并实现方法

setMethod("[", c("A", "integer", "missing", "ANY"),
    ## we won't support subsetting on j; dispatching on 'drop' doesn't
    ## make sense (to me), so in rebellion we'll quietly ignore it.
    function(x, i, j, ..., drop=TRUE)
{
    ## less clever: update slot, return instance
    ## x@slt = x@slt[i]
    ## x
    ## clever: by default initialize is a copy constructor, too
    initialize(x, slt=x@slt[i])
})

行动中:

> a = new("A", slt=1:5)
> a[3:1]
An object of class "A"
Slot "slt":
[1] 3 2 1

支持(隐式)许多签名有不同的策略,例如,您可能还希望支持逻辑和字符索引值,可能同时支持i和j。最直接的是“外观”模式,其中每个方法对常见类型的子集索引进行一些初步强制,例如,integer以允许重新排序和重复索引条目,然后使用{{ 1}}调用一个方法来完成对类进行子集化的工作。

callGeneric没有概念上的差异,除了想要尊重返回内容的语义而不是[[暗示的对象的另一个实例。对于[,我们有

$

> getGeneric("$")
standardGeneric for "$" defined from package "base"

function (x, name) 
standardGeneric("$", .Primitive("$"))
<bytecode: 0x31fce40>
<environment: 0x31f12b8>
Methods may be defined for arguments: x
Use  showMethods("$")  for currently available ones.

setMethod("$", "A",
    function(x, name)
{
    ## 'name' is a character(1)
    slot(x, name)
})

答案 1 :(得分:9)

我会像@Martin_Morgan建议您提到的运营商。我会补充几点:

1)我会小心定义$运算符来访问S4插槽(除非您打算从存储在特定插槽中的数据帧中访问一列?)。一般建议是编写getMySlot()setMySlot()等访问函数来获取所需的信息。您可以使用@运算符来访问这些插槽中的数据,尽管get和set最适合作为用户界面。使用$可能会让用户感到困惑,因为用户可能期望使用data.frame。请参阅Christophe Genolini的this S4教程,深入讨论这些问题。如果这不是您打算使用$的方式,请忽略我的建议(但教程仍然是一个很好的资源!)。

2)如果您要定义[[[继承其他类(如vector),您还需要定义el()(相当于[][[1L]],或者子集[])和length()中的第一个元素。我目前正在编写一个继承自数字的类,而数值方法将自动尝试使用您的类中的这些函数。如果课程是为了更有限或个人使用,这可能不是问题。

我道歉,我会留下这个作为评论,但我是新来的,我还没有代表!