Слоты класса против инициализации несовпадения сигнатур - PullRequest
1 голос
/ 31 марта 2012

Рассмотрим следующий класс S4:

setClass('Foo', representation(model='data.frame'))

setMethod('initialize', 'Foo',
      function(.Object, a, b) {
        .Object@model <- data.frame(a, b)
        .Object
      })

Его можно создать с помощью:

new('Foo', a=1:4, b=4:7)

Пока все хорошо.Однако, когда я пытаюсь создать подкласс Foo, я получаю ошибку.

setClass('Bar', contains='Foo')
>>> Error in data.frame(a, b) : argument "a" is missing, with no default

Лично я предпочел бы создать экземпляр класса Foo с явными аргументами, потому что код более ... хорошо, явный.Однако это не представляется возможным, не так ли?Похоже, что сигнатура initialize должна совпадать со слотами, которые есть у класса, иначе это проблема, ожидающая своего появления.Я не прав?

1 Ответ

3 голосов
/ 01 апреля 2012

Требуется, чтобы new вызывался без аргументов, new("Foo"), должен работать.Кроме того, вероятно, лучше, чтобы ваш метод инициализации принимал ..., callNextMethod и имел аргументы после ... (поскольку документально подтверждено, что initialize использует безымянные аргументы для инициализации содержащихсяклассы).Поэтому

setMethod(initialize, "Foo", function(.Object, ..., a=integer(), b=integer()) {
    callNextMethod(.Object, ..., model=data.frame(a, b))
})

Обычно каждый хочет изолировать пользователя от вызова new и вместо этого будет использовать конструктор Foo.Обычно конструктор выполняет любое приведенное вами принуждение вместо этого в методе initialize, поэтому метод initialize просто не указан.

Foo <- function(a=integer(), b=integer(), ...) {
    model <- data.frame(a, b)
    new("Foo", model=model, ...)
}
...