dotsMethods
位于 methods
包(package)。 说明
“...” 参数R函数被特殊对待,因为它匹配零个、一个或多个实际参数(以及对象)。添加了一个机制R允许 “...” 作为通用函数的签名。为此类函数定义的方法将在以下情况下被选择和调用:全部匹配 “...” 的参数来自指定的类或该类的某个子类。
在签名中使用"..."
从 2.8.0 版本开始R,可以根据特殊参数“...”调度(选择和调用)S4方法。目前,“...” 不能与其他形式参数混合:泛型函数的签名或者仅为“...”,或者不包含“...”。 (此限制可能会在未来版本中取消。)
给定一个合适的通用函数,可以通过调用 setMethod
以通常的方式指定方法。编写方法定义时,必须期望与 “...” 对应的所有参数都来自方法签名中指定的类,或者来自扩展该类的类(即该类的子类)。
通常,这些方法会将 “...” 传递给另一个函数,或者创建一个参数列表并对其进行迭代。请参阅下面的示例。
当您的计算适合多个现有类时,一种方便的方法可能是通过调用 setClassUnion
来定义这些类的并集。请参阅下面的示例。
"..."的方法选择和调度
有关一般讨论,请参阅Methods_Details。以下假设您已阅读该文档的“方法选择和调度”部分。
“...” 上选择的方法由调用 setMethod
中的单个类指定。如果“...”对应的所有实参都有这个类,则直接选择对应的方法。
否则,从第一个 “...” 参数开始计算每个参数的类以及该类的超类。对于第一个参数,合格的方法是适用于任何类的方法。对于引入先前未考虑的类的每个后续参数,合格的方法进一步限制为与参数的类或超类匹配的方法。如果不存在其他符合条件的类,则迭代将中断并选择默认方法(如果有)。
在迭代结束时,一种或多种方法可能是合格的。如果超过一个,则选择查找与实际参数距离最小的方法。对于每个参数,任何继承的方法都对应于一个距离,可从类定义的 contains
槽中获取。由于同一类可以出现多个参数,因此可能有多个与之相关的距离。将它们组合起来不可避免地是任意的:当前的计算使用最小距离。因此,例如,如果一个方法直接匹配一个参数,一个作为第一代超类,另一个作为第二代超类,则距离为 0、1 和 2。当前选择计算将对此方法使用距离 0。特别是,此选择标准倾向于使用与一个或多个参数类别完全匹配的方法。
与普通的方法选择一样,可能存在多个具有相同距离的方法。发出警告消息并选择其中一种方法(第一个遇到的方法,在本例中是相当任意的)。
请注意,虽然计算检查所有参数,但分派的基本成本随着参数中不同类的数量而增加,当后者很大时,可能比参数数量小得多。
实施细节
在 “...” 上调度的方法是在 2.8.0 版本中引入的R。相应的选择和调度的初始实现是在 R 函数中实现的,以便在研究新机制时保持灵活性。在此实现中,本地版本standardGeneric
被插入到通用函数的环境中。本地版本根据上述标准选择一个方法,并从通用函数的环境中调用该方法。这与不涉及 “...” 时 C 实现所采取的操作略有不同。除了需要额外的计算时间之外,该方法是在真正的函数调用中计算的,而不是由 C 版本构建的特殊上下文(无法在 R 代码中完全复制)。但是,在不同的计算结果的情况下到目前为止还没有遇到过,而且看起来可能性很小。
通过将继承的方法存储在所有方法的表中来缓存除 “...” 以外的参数上分派的方法,在下一个选择中可以在实际参数中使用相同的类组合找到该方法(但不用于继承搜索) 。基于“...”的方法也被缓存,但没有立即找到。如前所述,所选方法仅取决于 “...” 参数中出现的类集。这些类中的每一个都可以出现一次或多次,因此实际参数类的许多组合将产生相同的有效签名。选择计算首先计算并排序遇到的不同类。这给出了一个标签,该标签将缓存在所有方法的表中,从而避免在第一次出现后进一步搜索继承的类。对showMethods
的调用将公开此类继承的方法。
目的是当获得足够的经验后,“...” 函数将被添加到标准 C 代码中。同时,可能支持 “...” 与签名中其他参数的组合。
例子
cc <- function(...)c(...)
setGeneric("cc")
setMethod("cc", "character", function(...)paste(...))
setClassUnion("Number", c("numeric", "complex"))
setMethod("cc", "Number", function(...) sum(...))
setClass("cdate", contains = "character", slots = c(date = "Date"))
setClass("vdate", contains = "vector", slots = c(date = "Date"))
cd1 <- new("cdate", "abcdef", date = Sys.Date())
cd2 <- new("vdate", "abcdef", date = Sys.Date())
stopifnot(identical(cc(letters, character(), cd1),
paste(letters, character(), cd1))) # the "character" method
stopifnot(identical(cc(letters, character(), cd2),
c(letters, character(), cd2)))
# the default, because "vdate" doesn't extend "character"
stopifnot(identical(cc(1:10, 1+1i), sum(1:10, 1+1i))) # the "Number" method
stopifnot(identical(cc(1:10, 1+1i, TRUE), c(1:10, 1+1i, TRUE))) # the default
stopifnot(identical(cc(), c())) # no arguments implies the default method
setGeneric("numMax", function(...)standardGeneric("numMax"))
setMethod("numMax", "numeric", function(...)max(...))
# won't work for complex data
setMethod("numMax", "Number", function(...) paste(...))
# should not be selected w/o complex args
stopifnot(identical(numMax(1:10, pi, 1+1i), paste(1:10, pi, 1+1i)))
stopifnot(identical(numMax(1:10, pi, 1), max(1:10, pi, 1)))
try(numMax(1:10, pi, TRUE)) # should be an error: no default method
## A generic version of paste(), dispatching on the "..." argument:
setGeneric("paste", signature = "...")
setMethod("paste", "Number", function(..., sep, collapse) c(...))
stopifnot(identical(paste(1:10, pi, 1), c(1:10, pi, 1)))
参考
Chambers, John M. (2008) Software for Data Analysis: Programming with R Springer. (For the R version.)
Chambers, John M. (1998) Programming with Data Springer (For the original S4 version.)
也可以看看
有关方法的一般讨论,请参阅Methods_Details 和其中的链接。
相关用法
- R as 强制对象属于某个类
- R language-class 表示未评估语言对象的类
- R className 类名包含对应的包
- R BasicClasses 基本数据类型对应的类
- R callGeneric 从方法调用当前通用函数
- R findClass 查找类定义
- R setOldClass 注册旧式 (S3) 类和继承
- R ReferenceClasses 具有按引用处理的字段的对象(OOP 样式)
- R MethodsList 方法列表对象
- R setGroupGeneric 创建函数的组通用版本
- R StructureClasses 基本结构对应的类
- R showMethods 显示指定函数或类的所有方法
- R getMethod 获取或测试方法的定义
- R slot 正式类对象中的槽
- R S4groupGeneric S4组通用函数
- R methodUtilities 用于方法和 S-Plus 兼容性的实用函数
- R getClass 获取类定义
- R evalSource 使用源文件中的函数定义,无需重新安装包
- R is 对象是来自类吗?
- R isSealedMethod 检查密封方法或类
- R cbind2 按列或行组合两个对象
- R GenericFunctions 管理通用函数的工具
- R S3Part 包含 S3 类的 S4 类
- R nonStructure-class 基本类型的非结构 S4 类
- R selectSuperClasses 类的超类(特定类型)
注:本文由纯净天空筛选整理自R-devel大神的英文原创作品 The Use of ... in Method Signatures。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。