Как обрабатывать неизвестные методы / дженерики в R - PullRequest
1 голос
/ 19 июня 2019

Во многих языках есть специальные способы обработки неизвестных методов ( примеры ). Тот, с кем я больше всего знаком, это Python's __getattr__. Если кто-то вызывает метод, который вы не определили для класса, __getattr__ действует как универсальный и делает что-то .

Я читал о S4 и немного о R6, но я не нашел, как это сделать в R. Возможно ли это?

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Нет, не существует стандартного способа сделать это из определения вашего класса, как это было бы в python.

В Python вы бы сделали что-то вроде MyObject.my_method(), тогда как в R с S3 или S4 это будет my_method(MyObject), так что это будет похоже на my_function(MyObject). Разница лишь в том, что вызванная вами функция отправляет вызов адекватному методу. Определение этих методов для нескольких классов выполняется следующим образом:

mean <- function (x, ...) UseMethod("mean", x)
mean.numeric <- function(x, ...) sum(x) / length(x)
mean.data.frame <- function(x, ...) sapply(x, mean, ...)
mean.matrix <- function(x, ...) apply(x, 2, mean)
mean.default <- function(x, ...) {
  # do something
}

Однако, если вы вызываете функцию среднего для класса, для которого не определен ни один метод, решать это должна функция, а не класс.

Тогда у вас есть RC и S6 объекты, которые имеют более похожий на питон синтаксис (MyObject$my_method()), однако они просто выдают ошибку, что нет соответствующего поля или метода для класса, который вы использовали .

Error in envRefInferField(x, what, getClass(class(x)), selfEnv) : 
  "my_method" is not a valid field or method name for reference class “MyObject”

Вот некоторые сведения об OO-программировании в R .

0 голосов
/ 27 июня 2019

Уинстон Чанг предоставил отличную информацию здесь:
https://github.com/r-lib/R6/issues/189#issuecomment-506405998

Он объясняет, как вы можете создать универсальную функцию S3 $ для вашего класса, чтобы перехватывать неизвестные методы. Прочитайте его полный ответ для более подробной информации, но ключевая функция приведена ниже (Counter - это название класса).

`$.Counter` <- function(x, name) {
  if (name %in% names(x)) {
    .subset2(x, name)
  } else {
    function(...) {
      .subset2(x, "do")(name, ...)
    }
  }
}

"Если name находится в классе, сделайте это. Если нет, отправьте name (и любые аргументы) в функцию с именем do(), определенную в классе."

Хотя я пометил это как ответ (потому что это решает проблему), jkd все еще корректен:

Нет, не существует стандартного способа сделать это внутри определения вашего класса, как вы это сделали бы в python.

...