如何在R中使用S4对象编程

时间:2016-04-20 20:17:47

标签: r object s4

我的R脚本出了什么问题?我试图在另一个用户定义的对象(这里是" Book"对象)中使用用户定义对象的向量(这里是" Page"对象的向量) / p>

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 个答案:

答案 0 :(得分:2)

请记住,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的“矢量化”。第一步是将对象'Page'视为'Pages',其中对象模拟列而不是数据帧的行。 'Book'则没有Page对象的向量,只有一个Pages对象。这也意味着创建“书”的方法不同。