【问题标题】:Copying S4 base class instance into a derived object将 S4 基类实例复制到派生对象中
【发布时间】:2013-08-15 09:27:28
【问题描述】:

我有两个简单的类:

.A1 <- setClass("A1", 
            representation=representation( x1 ="numeric"),
            prototype = prototype(x1 = 10))

.A2 <- setClass("A2", contains="A1",
           representation=representation(x2="numeric"),
           prototype = prototype(x2 = 10))

setMethod("initialize", "A2",
      function(.Object, ..., x2 = .Object@x2)
      {
        callNextMethod(.Object, ..., x2 = x2)
      })

使用此代码一切正常:

a1 <- .A1(x1 = 3)
initialize(a1)

a2 <- .A2(x1 = 2, x2 = 4)
initialize(a2, x2 = 3)

.A2(a1, x2 = 2)

An object of class "A2"  # WORKS!
Slot "x2":
[1] 2

Slot "x1":
[1] 3

特别是最后一行工作,所以 a1 被复制到“A2”对象中。这 问题是如果也为基类定义“初始化”,最后一行没有 不再工作了:

setMethod("initialize", "A1",
      function(.Object, ..., x1 = .Object@x1)
      {
        callNextMethod(.Object, ..., x1 = x1)
      })

## I have to redefine also this initializer, otherwise it will call
## the default initializer for "A1" (it was stored in some lookup table?)
setMethod("initialize", "A2",
      function(.Object, ..., x2 = .Object@x2)
      {
        # your class-specific initialization...passed to parent constructor
        callNextMethod(.Object, ..., x2 = x2)
      })

现在我明白了:

.A2(a1, x2 = 2)
An object of class "A2"  # BAD!
Slot "x2":
[1] 2

Slot "x1":
[1] 10

我猜我的“A1”初始化程序有问题,有什么想法吗? 谢谢!

【问题讨论】:

    标签: r copy-constructor s4


    【解决方案1】:

    A1 初始化方法行为不正常,因为 x1 = .Object@x1 咨询 .Object,它对于构造函数是类的原型(对于您的示例 .A2(a1, x2=2),在初始化中,A1 方法 .Object 是从原型构造的A2 的值,所以 x1 被赋值为 10,x1 = .Object@x1 = 10 覆盖了 a1 提供的值。

    很难知道什么是通用解决方案。您可以测试缺失性

    setMethod("initialize", "A1", function(.Object, ..., x1) {
        if (!missing(x1))
            callNextMethod(.Object, ..., x1=x1)
        else 
            callNextMethod(.Object, ...)
    })
    

    或者做一些聪明的事情,也许使用 match.call,以避免多个插槽的组合问题。

    另一种方法似乎是实践中采用的方法,尽管它实际上只是回避了问题,是避免使用初始化方法,而是依赖单独的构造函数来进行任何数据按摩,如在此答案的Retaining copy construction 部分的第一个代码框。

    【讨论】:

    • 非常感谢您的回答,我不知道发生了什么。我的解决方案是避免为这两个类中的任何一个定义“初始化”泛型,并从原型中初始化所有内容。在我的实际课程中,有很多插槽,因此依赖默认初始化程序似乎对我来说是最简单的事情。我在 OOP 方面的经验很少,但是需要依靠很多技巧来做像上面这样相当合理的事情,这不是有点奇怪吗?非常感谢您对 S4 的所有回答,它们是很好的学习资源!
    • 是的,有点奇怪!可能为初始化设定的合同太复杂了。
    猜你喜欢
    • 2013-08-11
    • 2013-02-12
    • 2022-10-01
    • 1970-01-01
    • 2015-03-23
    • 2023-02-03
    • 2012-03-11
    • 2014-04-27
    • 1970-01-01
    相关资源
    最近更新 更多