2013-03-06 3 views
2

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

toy <- function(x){ 
    resA <- mean(x) 
    resB <- length(x) 

    output <- list(resA=resA, resB=resB, x=x) 
    class(output) <- "toy" 
    output 
} 

Когда мы достигаем результат в настоящее время с помощью

res <- toy(c(1:10)) 
res 

мы получаем весь список как результат, как и следовало ожидать. Но если мы определяем то также метод печати S3

`print.toy` <- function(x){ 
    print(x$resA) 
} 

мы можем дать стандартный вывод для печати, которая скрывает ненужную информацию (в этом случае resB и x), и пользователь видит только resA. Но это может вызвать некоторую путаницу, когда вы хотите применить дальнейшие вычисления на свой объект класса toy, например.

res <- toy(c(1:10)) 
res 
# Produces an error 
res + 1 
# Accesses the correct variable of class toy: 
res$resA + 1 

Мой вопрос теперь, есть способ определить элемент resA списка, чтобы быть стандартное значение класса S3, которые должны быть приняты, если не указано ни одной переменной, так что res + 1 вызов будет работать, как хорошо ?

Спасибо за это.

+1

Я думаю, вам нужно перегрузить '+' для этого. –

ответ

4

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

toy <- function(x) { 
    resA <- mean(x) 
    resB <- length(x) 

    structure(resA, x = x, b = resB, class = "toy") 
} 
print.toy <- function(x, ...) { 
    print(as.vector(x)) 
} 
t <- toy(1:10) 
t + 1 
# [1] 6.5 

Вам также необходимо переопределить [, поскольку метод по умолчанию не сохраняет атрибуты.

+0

Спасибо большое! «Структура» - это то, что я искал - в основном, как вы сказали, основная часть данных, а затем еще какая-то скрытая информация. –

+0

Играя с вашим ответом, я обнаружил, что функция '' $ .toy '<- function (x, y, ...) {attr (x, as.character (y))} 'делает доступные скрытые атрибуты в точности, что я имел в виду, еще раз спасибо! (Я не уверен, если было бы лучше отредактировать ваш ответ и добавить к нему эту функцию или оставить его здесь в комментарии ?!) –

+0

Я бы не рекомендовал делать это без лишних размышлений - это замалчивает тот факт, что ваш объект основан на объекте с атрибутами, а не в списке. – hadley

2

Как отмечает @Ari, вы могли бы сделать что-то вроде этого:

`+.toy` <- function(a, b) { 
    # you should check for class/mode/is.atomic here if necessary 
    a$resA <- a$resA + b 
    a 
} 

t <- toy(1:10) 
t + 1 
# [1] 6.5 
+0

Жаль, что перегрузка кажется единственным способом, потому что это приводит к перегрузке всего набора функций. Я надеялся немного на то, чтобы сделать вывод 'print' элементом по умолчанию, если не указан элемент списка. Таким образом, R извлекает этот элемент и выполняет запрошенную операцию на этом. –

+0

Пока я понимаю вашу точку зрения, так оно и должно быть. '+' не может по умолчанию принимать операции над списком или любым другим объектом. – Arun

Смежные вопросы