问题
Consider the following S4 class:
setClass('Foo', representation(model='data.frame'))
setMethod('initialize', 'Foo',
function(.Object, a, b) {
.Object@model <- data.frame(a, b)
.Object
})
It can be instantiated with:
new('Foo', a=1:4, b=4:7)
So far so good. However, when I try to subclass Foo I get an error.
setClass('Bar', contains='Foo')
>>> Error in data.frame(a, b) : argument "a" is missing, with no default
Personally, I would prefer to instantiate class Foo with explicit arguments because the code is more... well, explicit. However, this does not seem possible, does it? It looks like the signature of initialize
must match the slots that the class has, otherwise it's a problem waiting to happen. Am I wrong?
回答1:
The requirement is that new
called with no arguments, new("Foo")
, must work. Also, it's probably better practice for your initialize method to take ...
, to callNextMethod
, and to have arguments after the ...
(because initialize
is documented to use unnamed arguments for initializing contained classes). So
setMethod(initialize, "Foo", function(.Object, ..., a=integer(), b=integer()) {
callNextMethod(.Object, ..., model=data.frame(a, b))
})
Normally one wants to insulate the user from calling new, and will instead use a constructor Foo
. Typically the constructor does whatever coercion you might have instead put in the initialize method, so the initialize method is just not specified.
Foo <- function(a=integer(), b=integer(), ...) {
model <- data.frame(a, b)
new("Foo", model=model, ...)
}
来源:https://stackoverflow.com/questions/9957511/class-slots-vs-initialize-signature-mismatch