R S3 классы - изменение класса и возврат к тому же методу - PullRequest
4 голосов
/ 11 марта 2020

У меня есть вопрос о «правильном» способе что-то сделать с классами S3 в R. Что я хочу сделать, так это иметь метод, который изменяет класс и затем вызывает тот же метод для нового класса. Примерно так:

my_func <- function(.x, ...) {
  UseMethod("my_func")
}

my_func.character <- function(.x, ...) {
  return(paste(".x is", .x, "of class", class(.x)))
}

my_func.numeric <- function(.x, ...) {
  .x <- as.character(.x)
  res <- my_func(.x) # this should call my_func.character
  return(res)
}

И это работает. Когда я делаю следующее, я получаю класс character для обоих

> my_func("hello")
[1] ".x is hello of class character"
> my_func(1)
[1] ".x is 1 of class character"

Мой вопрос: это правильный способ сделать это? Что-то странное в повторном вызове того же метода после того, как я преобразовал класс (эта строка res <- my_func(.x)).

Я чувствовал, что NextMethod() должен как-то быть ответом, но я прочитал на нем куча документов (например, , это и , это ), но все они говорят об этом, когда он прыгает на следующий класс в списке классов, например, из data.frame до matrix, если у вас есть class(df) и получите, например, c("data.frame", "matrix").

Но никто из них не говорит об этой ситуации, когда вы конвертируете ее в совершенно другой класс, которого не было в исходной иерархии. Так что, возможно, NextMethod() не , что нужно использовать, но есть ли что-то еще, или я должен просто оставить это, как у меня?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 11 марта 2020

1) Если идея заключается в том, что my_fun c .numeri c выполняет дополнительную обработку, но также хочет использовать my_fun c .character, не повторяя это тогда в func.numeric установите .Class, а затем вызовите NextMethod следующим образом:

my_func.numeric <- function(.x, ...) {
  .Class <- "character"
  .x <- as.character(.x)
  NextMethod()
}

NextMethod возвращает результат, и после него можно дополнительно выполнить дополнительную обработку. Дополнительную информацию можно найти, введя ?NextMethod в R.

2) Если идея состоит в том, что числовые c и символьные методы можно комбинировать, тогда:

my.func.character <- my.func.numeric <- function(.x, ...) {
    .x <- as.character(.x)
    paste(".x is", .x, "of class", class(.x))
}

Также было бы возможно использовать метод по умолчанию для этого, если он еще не используется для чего-то другого.

3) Если идея только в том, что существует общий доступ функциональность, но вы не обязательно хотите использовать всю обработку символьного метода в методе цифр c или наоборот, затем определите функцию, вызываемую каждым из них:

my_func_impl <- function(.x, ...) paste(".x is", .x, "of class", class(.x))

my_func.character <- function(.x, ...) {
  # some procesing unique to this method
  my_func_impl(.x, ...)
}

my_func.numeric <- function(.x, ...) {
  # some procesing unique to this method
  my_func_impl(.x, ...)
}
0 голосов
/ 11 марта 2020

Самый стандартный способ - создать метод по умолчанию, например:

my_func.default <- function(.x, ...) {
  stopifnot(is.atomic(.x)) # throw an error if .x isn't an atomic vector
  .x <- as.character(.x)
  paste(".x is", .x, "of class", class(.x))
}
my_func("hello")
#> [1] ".x is hello of class character"
my_func(1)
#> [1] ".x is 1 of class character"
...