如何不覆盖泛型方法
Posted
技术标签:
【中文标题】如何不覆盖泛型方法【英文标题】:How not to overwrite generic methods 【发布时间】:2014-08-21 14:01:12 【问题描述】:我正在尝试了解 R 中的 s3 类系统。
文档说我需要为我想要创建的方法创建一个通用函数。
假设我想为类 XYZ
创建一个方法 foo
。
使用 R 拥有的所有包,我如何确定我没有覆盖以前创建的泛型方法?
Summary 是一个不好的例子,因为每个人都可能知道它已经存在,但我的泛型可能已经定义在我已经加载或我将加载的包中。
【问题讨论】:
问题不在于方法,而在于类。如果你的类与其他包不同,剩下的就变得微不足道了。 主要问题不是覆盖泛型(虽然这可以result in problems too),而是屏蔽非泛型,例如dplyr::filter
(泛型)掩蔽stats::filter
(非泛型) )。关于从其他包中屏蔽 methods,这通常可以避免,因为不难找到可能是唯一的类名(例如,如果不是lme4 位作者)。
让我们以通用摘要为例,并假设我不知道 R 摘要中的某处已被定义为通用。如果我创建 summary
您可以通过添加指向原始函数的默认方法将函数重新定义为泛型而不破坏原始函数。请参阅此处的要点gist.github.com/datalove/88f5a24758b2d8356e32
@RomanLuštrik 仅当您的包裹未附加时才会如此。一旦你附加了你的包,你的泛型可能会覆盖其他现有的函数(反之亦然)。这绝对是 R 的包系统的一大缺陷。
【参考方案1】:
我遇到过类似的问题,我想在这里发布一个部分解决方案,并在此过程中吸取一些经验教训。
我不确定问题是否真的是 S3 方法覆盖了通用方法,而是非 s3 方法(我已经确定了一些问题,即在lavaan
和 semTool
包中发送 summary
s4 方法失败)。
我们可以通过methods("foo")
或所有方法查看可用的方法
methods(class="XYZ")
的班级。
我们可以检查一个泛型是否已经注册
isGeneric("foo")
。
如果方法还没有注册,那么,我们需要设置一个泛型 using(summary
不是这种情况):
foo<- function(x) UseMethod("foo")
第一个问题是:
-
我们能够看到仅针对已加载包的方法;
有getS3method(f="foo",class="XYZ")
的选项,但它需要函数和类;
utils::getAnywere("foo")
更广泛,但也仅适用于已加载的包...
如果只存在 S3 方法(没有 S4 方法),这不是真正的问题,而且我们没有指定泛型,而只是指定新方法,并且我们确定尚未使用类名。
第二个问题是:
-
如果函数还关联了一个 S4 方法,显然,通过指定新的 s3 方法(即使是已经存在的泛型,如
summary
的情况)它会搞乱 S4 方法的发送
(i) 所以我们也可以专门跟踪 S3 方法 .S3methods("foo")
或特定类的 s3 方法 .S3methods(class="XYZ")
并在加载所有主要包后专门找出 S4 方法(例如使用 .S4methods("foo")
)担心……;
(ii) 识别对象类别;
(iii) 检查其文档中是否有任何类型的相应方法(显然某些 s4 方法在文档中不容易识别,无法在 s3 方法中轻松调用)
(iv) 如果 (iii) 不可用,则评估其结构;和
(v) 通过调用已识别的方法(如果可用)或从对象中提取所需的输出,考虑其结构,为特定类指定相应的 s3 方法...
(使用 .default 是另一种选择,但我认为需要仔细考虑)。
但是,尽管考虑到类对象结构来重新指定方法的替代方法对于summary
方法来说更容易一些,但对于其他功能来说,这可能是一项非常艰巨的工作......
我想应该有一个广泛的解决方案来自动考虑 s4 方法,但我对 S4 方法的有限知识目前无法在其中发展......
【讨论】:
以上是关于如何不覆盖泛型方法的主要内容,如果未能解决你的问题,请参考以下文章