Перезаписать метод, чтобы расширить его, используя исходную реализацию

Будь то в пакете или иногда в базе R, я иногда хочу добавить немного изюминки в существующую функцию. В большинстве случаев это незначительное изменение того, что должно происходить в начале или в конце функции (глупый пример: я бы хотел, чтобы функция cat включала новую строку в конце по умолчанию).

Теперь я знаю, что могу просто перезаписать существующий метод, назначив его имя моей новой реализации, НО: как же тогда я могу использовать старый? В случае cat мне пришлось бы сделать что-то вроде:

cat<-function(... , file = "", sep = " ", fill = FALSE, labels = NULL,
    append = FALSE)
{
  cat(..., "\n" , file = file, sep = sep, fill = fill, labels = labels,
    append = append)
}

Это означает использование «старого» cat в реализации нового. Теперь, если я что-нибудь понимаю о том, как работают вызовы и позднее связывание в R, это просто не удастся (бесконечная рекурсия).

Итак, есть ли способ добиться этого (в духе объектно-ориентированных переопределений функций), не прибегая к

  • дать моей новой функции другое имя (я хочу, чтобы она «просто работала»)
  • сохранение старой функции под другим именем (затем, когда я создаю эту функцию в другом сеансе R, я могу забыть о дополнительном шаге)
  • используя весь источник исходной функции (как сказал @Andrie: важно иметь максимально элегантное решение)

Существует ли парадигма для этого? Или как я могу сделать это самым безопасным способом? Или я просто слишком многого хочу?

Изменить Учитывая ответ @Andrie: это можно сделать довольно просто. Однако трюк Андри не сработает, если я хочу изменить поведение некоторой функции в пакете, которая вызывается другой функцией в пакете.

В качестве примера: я сделал множество дополнений к графическим функциям пакета glmnet. Но если вы посмотрите на plot.cv.glmnet и тому подобное, вы увидите, что они перенаправляют вызов другой функции в этом пакете, поэтому мне действительно нужно внедрить мою новую версию в пакет (что, кстати, можно сделать с помощью reassignInPackage). Но тогда, конечно, префикс пространства имен не удастся, потому что я только что заменил версию с пространством имен. Этот пример не так надуман, как может показаться: я был там довольно много раз. С другой стороны, может быть, кто-то возразит/сможет возразить, что в таком случае я должен отказаться от своих требований? Какой тогда будет лучший путь?


person Nick Sabbe    schedule 10.11.2011    source источник


Ответы (1)


Если я вас правильно понял, я думаю, что это просто вопрос ссылки на namespace::function, т.е. в этом случае используйте base::cat внутри вашей функции.

Например:

cat <- function(... , file = "", sep = " ", fill = FALSE, labels = NULL,
    append = FALSE)
{
  base::cat(..., "\n" , file = file, sep = sep, fill = fill, labels = labels,
      append = append)
}

> cat("Hello", "world!")
Hello world! 
> cat("Text on line 2")
Text on line 2 
person Andrie    schedule 10.11.2011
comment
‹хлопает по лбу/›. Отличное наблюдение (как обычно с вашей стороны) очевидного (как обычно с моей стороны). В любом случае, я немного подниму планку (см. мою правку через несколько минут). - person Nick Sabbe; 10.11.2011