我们可以将 S3 灵活性与 S4 表示检查结合起来吗?
Can we combine S3 flexibility with S4 representation checking?
我正在寻找一种方法来验证我的包中的 S3 对象 Momocs。
包的早期版本是使用 S4 编写的,然后为了灵活性,我转回了 S3,因为用户更喜欢 S3,因为我真的不需要多重继承,etc.。此更改的主要成本实际上是失去了 S4 表示/有效性检查。
我的问题如下:我们如何防止无意中 "unvalidate" S3 对象,例如试图扩展现有方法或操纵对象结构?
我已经编写了一些 validate
函数,但到目前为止,我只在关键步骤之前进行验证,通常是那些将对象从 class 转换为另一个对象的步骤。
我的问题是:
- 我想吃蛋糕吗(S3 灵活性和 S4 表示检查)?在那种情况下,我需要在我的包的所有方法中添加我的
validate
函数?
- 或者在 S3 之上有更聪明的方法,比如 "any time we do something on an object of a particular class, call a
validate
function on it"?
最简单的方法是为每个 class 编写一个验证函数,并在 S3 方法分派之前或在每个 class 的方法中通过它传递对象。下面是一个简单的验证函数示例,名为 check_example_class
用于 class "example_class"
:
的对象
check_example_class <- function(x) {
stopifnot(length(x) == 2)
stopifnot("a" %in% names(x))
stopifnot("b" %in% names(x))
stopifnot(is.numeric(x$a))
stopifnot(is.character(x$b))
NULL
}
print.example_class <- function(x, ...) {
check_example_class(x)
cat("Example class object where b =", x$b, "\n")
invisible(x)
}
# an object of the class
good <- structure(list(a = 1, b = "foo"), class = "example_class")
# an object that pretends to be of the class
bad <- structure(1, class = "example_class")
print(good) # works
## Example class object where b = foo
print(bad) # fails
## Error: length(x) == 2 is not TRUE
我正在寻找一种方法来验证我的包中的 S3 对象 Momocs。
包的早期版本是使用 S4 编写的,然后为了灵活性,我转回了 S3,因为用户更喜欢 S3,因为我真的不需要多重继承,etc.。此更改的主要成本实际上是失去了 S4 表示/有效性检查。
我的问题如下:我们如何防止无意中 "unvalidate" S3 对象,例如试图扩展现有方法或操纵对象结构?
我已经编写了一些 validate
函数,但到目前为止,我只在关键步骤之前进行验证,通常是那些将对象从 class 转换为另一个对象的步骤。
我的问题是:
- 我想吃蛋糕吗(S3 灵活性和 S4 表示检查)?在那种情况下,我需要在我的包的所有方法中添加我的
validate
函数? - 或者在 S3 之上有更聪明的方法,比如 "any time we do something on an object of a particular class, call a
validate
function on it"?
最简单的方法是为每个 class 编写一个验证函数,并在 S3 方法分派之前或在每个 class 的方法中通过它传递对象。下面是一个简单的验证函数示例,名为 check_example_class
用于 class "example_class"
:
check_example_class <- function(x) {
stopifnot(length(x) == 2)
stopifnot("a" %in% names(x))
stopifnot("b" %in% names(x))
stopifnot(is.numeric(x$a))
stopifnot(is.character(x$b))
NULL
}
print.example_class <- function(x, ...) {
check_example_class(x)
cat("Example class object where b =", x$b, "\n")
invisible(x)
}
# an object of the class
good <- structure(list(a = 1, b = "foo"), class = "example_class")
# an object that pretends to be of the class
bad <- structure(1, class = "example_class")
print(good) # works
## Example class object where b = foo
print(bad) # fails
## Error: length(x) == 2 is not TRUE