Слоты класса против инициализации несовпадения сигнатур

Рассмотрим следующий класс 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 ответ

Решение

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

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

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

Foo <- function(a=integer(), b=integer(), ...) {
    model <- data.frame(a, b)
    new("Foo", model=model, ...)
}
Другие вопросы по тегам