1

2 つの単純なクラスがあります。

.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」の初期化子に何か問題があると思いますが、アイデアはありますか? ありがとう!

4

1 に答える 1

2

A1 initialize メソッドx1 = .Object@x1は、コンストラクターのクラスのプロトタイプである .Object を参照するため、動作が正しくありません (例.A2(a1, x2=2)では、initialize,A1-method .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 を使用して何か賢いことを行い、スロットが 2 つ以上ある場合の組み合わせの問題を回避します。

実際には問題を回避するだけであるにもかかわらず、実際に採用されているように見える別のアプローチは、初期化メソッドの使用を避け、代わりに、最初のコードボックスのように、データのマッサージを行うために別のコンストラクターに依存することです。この回答の保持コピー構築セクションの。

于 2013-08-15T22:43:08.730 に答える