将S4基类实例复制到派生对象中 [英] Copying S4 base class instance into a derived object

查看:89
本文介绍了将S4基类实例复制到派生对象中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个简单的类:

.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)
      })

使用此代码,一切正常:

Using this code everything works:

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对象内。
的问题是,如果还为基类定义了 initialize,则最后一行不再
起作用:

In particular the last line work, so a1 gets copied inside the "A2" object. The problem is that if define "initialize" also for the base class the last line doesn't work anymore:

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初始化程序有问题,有什么想法吗?
谢谢!

I guess there is something wrong with my initializer of "A1", any ideas? Thanks!

推荐答案

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

The A1 initialize method mis-behaves because x1 = .Object@x1 consults .Object, which for the constructor is the prototype of the class (for your example .A2(a1, x2=2), in the initialize,A1-method .Object is constructed from the prototype of A2, so x1 is assigned 10, and x1 = .Object@x1 = 10 over-writes the value provided by a1.

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

It's hard to know what a general solution is. You could test for missing-ness

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

或者做一些聪明的事情,也许

or do something clever, maybe with match.call, to avoid a combinatorial problem with more than a couple of slots.

另一种方法,尽管实际上只是采用了match.call,以避免在多个插槽中出现组合问题。

Another approach, which seems to be the one adopted in practice even though it really just side-steps the problem, is to avoid using an initialize method, and instead rely on a separate constructor to do any data massaging, as in the first code box of the Retaining copy construction section of this answer.

这篇关于将S4基类实例复制到派生对象中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆