質問に対する新しい回答を提供するのではなく、私のコメントを補足します。これは、引数を位置で一致させるソリューションです (クラス B の追加の表現を指定しているため)。
.A <- setClass("A", representation(a="character"))
.B <- setClass("B", representation(b="numeric"),
prototype(a="hello"),
contains="A")
.A()
とへの呼び出しを.B()
置き換えます。あるレベルでは、これはシンタックス シュガーですが、オブジェクトの構築をより透過的にすることができますnew("A")
new("B")
## construct an object using B's prototype, like new("B", b=1:3)
> .B(b=1:3)
An object of class "B"
Slot "b":
[1] 1 2 3
Slot "a":
[1] "hello"
## construct an object using A's prototype, like new("B", new("A"), b=1:3)
> .B(.A(), b=1:3)
An object of class "B"
Slot "b":
[1] 1 2 3
Slot "a":
character(0)
new
(2 番目の例では、またはへの名前のない引数がB
継承されたクラスの初期化に使用されるという事実を使用しています)。
.A
orを直接使用しなければならないのは、ユーザーにとってあまり友好的ではありません.B
。たとえば、署名が正しく...
、「クラス A のスロットの定義を参照」として文書化されているためです。これにより、OOP の強みであるインターフェイスと実装の分離が妨げられます。また、最後のコード チャンク (.B(.A(a=a), b=b)
または.B(a=a, b=b)
) のいずれかの動作が意図されていない可能性があります。代わりに、ユーザーに公開される関数を提供し、おそらく初期データ マッサージを行います。
A <- function(a=character(), ...) {
## nothing special, just a public constructor
.A(a=a, ...)
}
B <- function(b, a="hello", ...) {
a <- tolower(a) ## no SHOUTing!
.B(A(a=a), b=b) ## A's public interface; no need for B to know A's details
}
関数 A と B はインターフェイスを定義し、コンストラクターをクラス定義に関連付けることなく、ユーザーに受け入れ可能な引数に関するヒントを提供し、予備的なデータ マッサージを実行します。後者はinitialize
メソッドを不要にすることができますが、これは良いことです。なぜなら、これらは複雑なコントラクト(初期化してコピー コンストラクターにする必要があり、上で見たように、名前のない引数は基本クラスを初期化する必要がある) を持っているからです。違う。
ほとんどの場合、これらは私の意見です。