微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

R:使用通用方法修改现有 S3 对象的属性

如何解决R:使用通用方法修改现有 S3 对象的属性

假设我有一个具有两个属性的类的构造函数,其中一个已启动,另一个设置为 NULL

myclass <- function(data) {
  structure(
    list(data1 = data,data2 = NULL),class = "myclass")
}

还有一个泛型:

myadd <- function(obj,x) {
  UseMethod("myadd")
}

myadd.myclass <- function(obj,x) {
  obj$data2 = obj$data1 + x
}

当我这样做时:

mc = myclass(1)
myadd(mc,2)

属性 data2 不会改变:

> mc
$data1
[1] 1

$data2
NULL

attr(,"class")
[1] "myclass"

显然,当我将结果分配给变量时:

tmp = myadd(mc,2)

我得到了结果:

> tmp
[1] 3

如何用泛型函数修改现有对象的属性?这样做甚至是犹太洁食吗?

我猜我遗漏了一些关于 R 中的 S3 类或关于 OOP 的关键信息。任何提示表示赞赏。

解决方法

1) 将它传回 当试图修改它时,R 会在函数中复制 obj。原始 obj 没有改变。这个想法是 R 是一种函数式语言,可以最大限度地减少副作用。

将其传回给调用者并在调用者中分配。

myadd.myclass <- function(obj,x) {
  obj$data2 = obj$data1 + x
  obj
}

mc <- myclass(1)
mc <- myadd(mc,2)
mc
## $data1
## [1] 1
##
## $data2
## [1] 3
##
## attr(,"class")
## [1] "myclass"

2) 替换方法 另一种可能是定义替换函数:

"myadd<-" <- function(x,...,value) UseMethod("myadd<-")
"myadd<-.myclass" <- function(x,value) { x$data2 <- x$data1 + value; x }

mc <- myclass(1)
myadd(mc) <- 2
mc
## $data1
## [1] 1
##
## $data2
## [1] 3
##
## attr(,"class")
## [1] "myclass"

3) 环境 另一种方法是使用环境而不是列表。

myclass <- function(data) {
    structure(local({
      data1 = data
      data2 = NULL
      environment()
    }),class = c("myclass","environment"))
}

# next two functions are same as in question
myadd <- function(obj,x) UseMethod("myadd")
myadd.myclass <- function(obj,x) obj$data2 = obj$data1 + x

obj <- myclass(1)
myadd(obj,2)
as.list(obj)
## $data1
## [1] 1
##
## $data2
## [1] 3

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。