【问题标题】:How to find the default construstor methods for a class如何找到类的默认构造方法
【发布时间】:2016-08-02 03:30:31
【问题描述】:

问题来自于对包进行试验,使用new(Class = 'ddmatrix', Data = X)ddmatrix(Data = X) 查找会产生不同的结果,其中X 是一个矩阵(可以认为类ddmatrix 是一个转换后的类matrix)。

文档

在包中,定义了一个S4类ddmatrixsetGeneric(name = 'ddmatrix') 的通用构造函数。此外,pacakge 定义setMethod('ddmatrix', signature = 'matrix', ...) 如下:

 setMethod("ddmatrix", signature(data="matrix"), 
              function(data, nrow=1, ncol=1, byrow=FALSE, ...
                       bldim=.pbd_env$BLDIM, ICTXT=.pbd_env$ICTXT)
    {
    dim(data) <- NULL
    ret <- ddmatrix(data=data, nrow=nrow, ncol=ncol, byrow=byrow, bldim=bldim, ICTXT=ICTXT)    
    return( ret )
}
)

我很困惑在上述setMethod('ddmatrix', signature = 'matrix') 步骤中如何使用方法ddmatrix。这个ddmatrix 方法是通用ddmatrix 的默认方法吗?

同时,当调用new('ddmatrix', Data = X) 时,它将调用哪个方法从matrix 对象构建一个新的ddmatrix 对象? new函数是:

function (Class, ...) 
{
    ClassDef <- getClass(Class, where = topenv(parent.frame()))
    value <- .Call(C_new_object, ClassDef)
    initialize(value, ...)
}

问题

要回答new('ddmatrix')ddmatrix() 之间的差异,我认为一种方法是找到默认构造函数。同时,包中还定义了setMethod('ddmatrix', signature = 'vector',...),这是默认的吗?

【问题讨论】:

    标签: r class object s4


    【解决方案1】:

    在某种程度上,这取决于作者。许多人将new()@slot()(用于插槽访问)视为严格针对包开发人员——这些将实现细节直接暴露给用户——并且更喜欢编写将接口放在上面的构造函数和访问器执行的顶部。您正在考虑的包似乎就是这种情况,其中ddmatrix() 是面向用户的构造函数。

    作者似乎实现了一种外观模式,其中几种不同的方法在调用另一个函数/方法进行实际对象构造之前进行相对较小的数据转换。从您显示的内容来看,似乎 ddmatrix,matrix-method 调用了 ddmatrix,vector-method (因为在 ddmatrix,matrix-method 内部,函数设置了dim(data) &lt;- NULL,将矩阵转换为向量,然后调用ddmatrix() 现在调度到向量方法),这通过new()https://github.com/RBigData/pbdDMAT/blob/master/R/constructors.r#L191构造对象。不同的包作者可能会采用不同的设计,其中几个方法分别调用new()

    文档通常也有帮助,例如,?ddmatrix 不讨论通过 new() 直接构造对象。

    这是一个更简单的例子。我创建了一个类“A”,其中包含一个数字向量的单个插槽

    setClass("A", slots=c(x="numeric"))
    

    这里我创建了一个构造函数,因为我希望用户看到类的接口,而不是它的实现

    A = function(x=numeric())
        new("A", x=x)
    

    到目前为止,A()new("A") 返回一个具有相同结构的对象,例如,

    > new("A")
    An object of class "A"
    Slot "x":
    numeric(0)
    
    > A()
    An object of class "A"
    Slot "x":
    numeric(0)
    

    也许作为“A”类的开发者,我想要一个“A”类的未初始化对象将“NA”作为槽x的值,所以我修改了

    A = function(x = NA_real_)
        new("A", x=x)
    

    现在直接调用 new() 会返回与调用 A() 不同的对象

    > new("A")
    An object of class "A"
    Slot "x":
    numeric(0)
    
    > A()
    An object of class "A"
    Slot "x":
    [1] NA
    

    哪一个是“正确的”?好吧,两者都是正确的,但作为类的创建者,我打算让用户通过调用函数 A() 创建一个类“A”的对象。

    将接口(使用A() 构造对象)与实现(使用new() 构造对象)分开的一个典型原因是,实现对用户来说并不明显。 ddmatrix() 函数似乎就是这种情况——由于只有包作者需要知道的原因,将 R 矩阵存储为包含维度信息的向量很方便。我想一个简单的等价物可能是

    setClass("A", slots=c(data="numeric", nrow="integer", ncol="integer"))
    A = function(m=matrix(0, 0, 0)) {
        stopifnot(is(m, "matrix"))
        new("A", data=as.vector(m), nrow=nrow(m), ncol=ncol(m))
    }
    

    例如

    > A(matrix(1:10, 5))
    An object of class "A"
    Slot "data":
     [1]  1  2  3  4  5  6  7  8  9 10
    
    Slot "nrow":
    [1] 5
    
    Slot "ncol":
    [1] 2
    

    作者为什么要这样做?作为用户,这对我们来说并不重要。为什么我们不能通过调用m = matrix(1:10, 5); new("A", data=as.vector(m), nrow=nrow(m), ncol(m)) 创建相同的对象?我们可以,但是当作者决定更改他们的实现以便存储每行开头的偏移量时,我们必须了解作者做了什么并更新我们的代码。

    【讨论】:

    • 感谢您的回答。顺便说一句,你的最后一句话是什么意思,你的意思是从帮助中可以看出ddmatrix方法与new没有关系?
    • 我的意思是作者告诉你如何使用他们的软件,他们说使用ddmatrix() 来构造一个对象。另一位作者可能写过文档说要使用new()
    • 如你所说,在 (github.com/RBigData/pbdDMAT/blob/master/R/constructors.r#L191) 方法调用new() 来构造,但是new 调用什么?我认为ddmatrix对象应该有一个最基本的构造函数
    • 要查看new() 调用的内容,请在命令行中键入new——但这是包开发人员业务,而不是最终用户业务。包开发人员打算让您使用ddmatriix() 方法之一。按照设计,所有方法都指向 ddmatrix,vector-method,因此您可能会将其视为最基本的构造函数。
    • 感谢您的帮助。但是,正如我所提到的,使用 new('ddmatrix', X)ddmatrix(X) 会产生不同的结果。所以我想弄清楚是什么原因造成的。我的理解是应该有一个基本的方法。 new 在使用new() 构造对象时调用,并且在调用ddmatrix() 运行到position 时也使用此基本方法,并且之前的代码有所不同。 new调用`value
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    相关资源
    最近更新 更多