修改S3对象而不返回它?

Chr*_*ris 6 r r-s3

我是 R 中面向对象编程的新手,并且正在努力解决如何正确编写修改对象的函数。

这个例子有效:

store1 <- list(
  apples=3,
  pears=4,
  fruits=7
)
class(store1) <- "fruitstore"
print.fruitstore <- function(x) {
  paste(x$apples, "apples and", x$pears, "pears", sep=" ")
}
print(store1)
addApples <- function(x, i) {
x$apples <- x$apples + i
x$fruits <- x$apples + x$pears
return(x)
}
store1 <- addApples(store1, 5)
print(store1)
Run Code Online (Sandbox Code Playgroud)

但我想应该有一种更干净的方法来做到这一点而不返回整个对象:

addApples(store1, 5)  # Preferable line...
store1 <- addApples(store1, 5)  # ...instead of this line
Run Code Online (Sandbox Code Playgroud)

在 R 中编写修改函数的正确方法是什么?“<<-”?

更新:感谢大家为 R 中的 OOP 编写的 Rosetta Stone。内容非常丰富。我试图解决的问题在流程方面非常复杂,因此参考类的刚性可能会给结构带来帮助。我希望我可以接受所有回复作为答案,而不仅仅是一个。

Ram*_*ath 3

这是一个参考类实现,如评论之一所建议。基本思想是建立一个名为 的引用类,Stores它具有三个字段:applespearsfruits(编辑为访问器方法)。该initialize方法用于初始化一个新的存储,该addApples方法将苹果添加到存储中,而该show方法对于其他对象来说是等效的print

Stores = setRefClass("Stores", 
  fields = list(
    apples = "numeric",
    pears  = "numeric",
    fruits = function(){apples + pears}
  ), 
  methods = list(
    initialize = function(apples, pears){
      apples <<- apples
      pears <<- pears
    },
    addApples = function(i){
      apples <<- apples + i
    },
    show = function(){
      cat(apples, "apples and", pears, "pears")
    }
  )
)
Run Code Online (Sandbox Code Playgroud)

如果我们初始化一个新存储并调用它,这就是我们得到的

FruitStore = Stores$new(apples = 3, pears = 4)
FruitStore

# 3 apples and 4 pears
Run Code Online (Sandbox Code Playgroud)

现在,调用该addApples方法,让我们向商店添加 4 个苹果

FruitStore$addApples(4)
FruitStore

# 7 apples and 4 pears
Run Code Online (Sandbox Code Playgroud)

编辑。根据哈德利的建议,我更新了我的答案,因此fruits现在它是一种访问器方法。apples当我们向商店添加更多内容时,它会不断更新。谢谢@哈德利。

  • 似乎“fruits”不应该是一个字段,而应该是一个计算方法(或者如果你想真正花哨,你可以做一个访问器方法,这样“FruitStore$fruit”仍然可以工作) (2认同)