R:使用通用方法修改现有 S3 对象的 属性
R: modifying property of an existing S3 object with a generic method
假设我有一个 class 的构造函数,它有两个属性,一个已启动,另一个设置为 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 classes 或一般 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
假设我有一个 class 的构造函数,它有两个属性,一个已启动,另一个设置为 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 classes 或一般 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