问题
I realized the benefit of using S3 class structures. Is there any recommendation which variant to use:
fun.class1 <- function(x, ...)
fun.class2 <- function(x)
It seems, they always work both...
Reproducible example:
fun.default <- function(x) {
print("default")
return(x)
}
fun.class1 <- function(x, ...) {
print("class1 ellipsis")
res <- x[y]
return(res)
}
fun.class2 <- function(x) {
print("class2 only x")
res <- x[y]
return(res)
}
my_fun <- function(x) {
res <- UseMethod("fun")
return(res)
}
x <- structure(c(1, 2), class = c("numeric", "class1"))
y <- 1
my_fun(x)
# [1] "class1 ellipsis"
# [1] 1
x <- structure(c(1, 2), class = c("numeric", "class2"))
y <- 1
my_fun(x)
# [1] "class1 ellipsis"
# [1] 1
回答1:
In Short:
Make your interfaces as small as possible.
Translated to your ellipsis question: Only use an ellipsis, when you really need it.
IMHO you should only introduce an ellipsis when you really use it. I can think of three cases I have seen so far:
- Some of your S3 classes need arguments others don't need;
- Some (or all) of your S3 classes use non-standard evaluation to evaluate some arguments. Therefore you might need an interface that is tolerant to a changing amount of arguments;
- @Roland's point to be tolerant with users that specify unused arguments.
In short I'd suggest the following:
As long as you are programming S3 classes that are mainly used by yourself or called by another function: Don't introduce any ellipsis argument just because you might use it someday in the future. Only introduce the arguments you really use. Introduce the ellipsis as soon as one of the use cases above is needed.
Hope this helps.
And another hint: It seems, they always work both... No, I don't think so. In your example they work all, because they find y
in the global environment. See also here. As far as I can see you should think of the two versions as my_fun(x, ...)
respectively my_fun(x, y)
..
来源:https://stackoverflow.com/questions/58131498/correct-implementation-of-a-s3-method-when-should-i-use-ellipsis