Как переопределить оператор @ для доступа к слотам объекта S4 в R - PullRequest
0 голосов
/ 30 октября 2019

Я работаю над проектом, в котором мне нужны сложные объекты S4 с несколькими слоями списка. Мне интересно, если это способ изменить функцию @, чтобы я мог получить доступ к данным на самом детальном уровне элегантным способом. Чтобы проиллюстрировать мою проблему, я создал пример объекта S4 ниже, и моя цель состоит в том, чтобы изменить функцию @, чтобы я мог достичь ниже:

jack <- new("Person", name = "Jack", other_info = list(age = 30, gender = "male")
jack@age 
# 30

Я пробовал много других способов, таких как создание универсальной функции, такой как%@%, но иметь дело с приоритетом оператора чрезвычайно сложно.

Ответы [ 2 ]

0 голосов
/ 30 октября 2019

Если вы используете классы R6, вы можете сделать что-то подобное с активными привязками.

Person <- R6::R6Class("Person",

public=list(
    name=NULL,
    initialize=function(name, age, gender)
    {
        self$name <- name
        private$other_info$age <- age
        private$other_info$gender <- gender
    }
),

active=list(
    age=function()
    {
        private$other_info$age
    },
    gender=function()
    {
        private$other_info$gender
    }
),

private=list(
    other_info=list(
        age=NULL,
        gender=NULL
    )
))

jack <- Person$new("jack", 42, "male")

jack$age
# [1] 42
0 голосов
/ 30 октября 2019

В дополнение к моему комментарию выше, я думаю, что есть неправильное понимание того, что @ делает в контексте объектов S4.

Давайте создадим новый Person класс

setClass(
    "Person",
    representation(
        name = "character",
        other_info = "list"))

и определите экземпляр согласно вашему примеру

jack <- new("Person", name = "Jack", other_info = list(age = 30, gender = "male"))

Обратите внимание, что jack имеет два слота, к которым можно получить доступ с помощью оператора @;у нас есть jack@name (к которому также можно получить доступ с помощью slot(jack, "name")) и jack@other_info (или slot(jack, "other_info")).

Для доступа к конкретным данным в определенных слотах используется OOP-путь kinda-sorta (см. @ Комментарий HongOoi) будет определять метод доступа

setGeneric("get_age", function(object) standardGeneric("get_age"))
setMethod("get_age", signature(object = "Person"), function(object) object@other_info$age)

Тогда мы можем сделать

get_age(jack)
#[1] 30
...