Как использовать S4 объектное программирование в R

Что не так с моим сценарием R? Я пытаюсь использовать вектор пользовательских объектов (здесь вектор объектов "Страница") в другом пользовательском объекте (здесь объект "Книга")

setClass("Page",
      slots = c(PageNo = "numeric",     #scalar
                Contents = "character") #vector of strings
)

setClass("Book",
      slots = c(Pages = "vector",       # Something wrong here? vector of pages ? "Page" or vector" or "list"
                Title = "character")    #vector of strings
)

setGeneric(name="AddPage", def=function(aBook, pageNo){standardGeneric("AddPage")})
setMethod(f="AddPage", signature="Book",
      definition=function(aBook, pageNo)
      {
          page1 = new("Page")
          page1@PageNo = pageNo
          aBook@Pages = c(aBook@Pages, page1) # Something wrong here?
      }
)

book1 = new("Book")
book1@Title = "Sample Book"
book1
book1@Pages
AddPage(book1, 1)
AddPage(book1, 2)
book1@Pages

1 ответ

Помните, что R не использует ссылочную семантику, поэтому AddPage(book1, 1) создает копию book1 и обновляет ее. В методе вы не возвращаете обновленный объект, а book1 остается неизменным.

Обновите метод, чтобы он возвращал измененный объект

setMethod(f="AddPage", signature="Book",
      definition=function(aBook, pageNo)
      {
          page1 = new("Page")
          page1@PageNo = pageNo
          aBook@Pages = c(aBook@Pages, page1) # Something wrong here?
          aBook
      }
)

и присвоить возвращаемое значение старой переменной

book1 = AddPage(book1, 1)

Но это очень неэффективный подход - линия aBook@Pages = c(aBook@Pages, page1) делает копию всех существующих страниц (справа, чтобы создать более длинный вектор; он масштабируется с квадратом числа страниц, добавленных в книгу), а затем копирует всю книгу (для назначения). Кроме того, создание отдельных объектов стоит дорого и не использует "векторизацию" R. Первым шагом является представление об объекте "Страница" вместо "Страницы", где объект моделирует столбцы, а не строки фрейма данных. В этом случае "Book" не имеет вектора объектов Page, а имеет один объект Pages. Это также подразумевает другой подход к созданию вашей "книги".

Другие вопросы по тегам