Учитывая ваши заявленные намерения, я не думаю, что ссылочные классы - это то, что вы здесь ищете. Ссылочные классы могут быть очень эффективными для многих случаев использования, но если ваша цель - сохранить интерфейс в виде списка для вашего нового класса, т. Е. Он может обращаться к функциям generi c, как если бы это был список, вам следует поискать в другом месте.
Любой создаваемый вами объект ссылочного класса представляет собой особый тип среды. Для начала это означает, что стандартное подмножество списка, например aObj[[1]]
, просто не будет работать. Единственная причина, по которой ваш пример позволяет вам это сделать, заключается в том, что ваше определение A
не работает и фактически не возвращает правильный объект ссылочного класса:
A <- setRefClass(
Class = "A",
contains = "list",
fields = c(
a = "numeric"
)
)
aObj <- A()
is.environment(aObj)
#> [1] FALSE
Причина, по которой оно не работает, заключается в том, что ссылочный класс может наследовать только от другого ссылочного класса или от класса S4.
Теперь вы могли бы реализовать ссылочный класс, где основным элементом данных является список и разделяет некоторые функции списка вот так:
A <- setRefClass(
Class = "A",
fields = c(a = "list"),
methods = list(
show = function() {
cat("A special list of type A containing:\n");
methods::show(.self$a)
},
append = function(x) {.self$a <- base::append(.self$a, x); return(.self)}
)
)
# Functions to convert back and forwards between A and normal list
as.list.A <- function(x) x$a
as.A <- function(x) A(a = as.list(x))
aObj <- A()
aObj
#> A special list of type A containing:
#> list()
aObj$append(1:3)
#> A special list of type A containing:
#> [[1]]
#> [1] 1
#>
#> [[2]]
#> [1] 2
#>
#> [[3]]
#> [1] 3
Но это не решает вашу проблему, связанную с желанием иметь возможность доступа путем разделения на подмножества или наследования полезных характеристик списка. Итак, что вы можете сделать?
Я думаю, что с точки зрения функциональности вы ищете класс S3. Возможно, реализация чего-то вроде этого, где мы просто определяем простой конструктор объекта и несколько обобщений:
A <- function(a = numeric()) structure(list(a = a), class = c("A", "list"))
as.list.A <- function(x) {class(x) <- "list"; x;}
str.A <- function(x) cat("A magical list of wonders called",
deparse(substitute(x)), "\n")
print.A <- function(x) {
cat("A special list of type A containing:\n")
print(as.list(x))
}
, который ведет себя следующим образом:
aObj <- A(a = 1:3)
aObj
#> A special list of type A containing:
#> $a
#> [1] 1 2 3
aObj[[1]] <- 1:4
aObj[[2]] <- 2:5
aObj
#> A special list of type A containing:
#> $a
#> [1] 1 2 3 4
#>
#> [[2]]
#> [1] 2 3 4 5
str(aObj)
#> A magical list of wonders called aObj
Потому что aObj
эффективно наследуется от list, любые общие c функции, которые вы не объявили, будут использовать общие c методы, как если бы это был обычный список. Это позволяет вам делать такие вещи, как:
lapply(aObj, mean)
#> $a
#> [1] 2.5
#>
#> [[2]]
#> [1] 3.5
Создано 01.07.2020 пакетом REPEX (v0.3.0)