我正在尝试将R中的@
运算符转换为S3系统的通用函数。
基于编写R扩展:添加新泛型的章节,我尝试为@
实现泛型,如下所示:
`@` <- function(object, name) UseMethod("@")
`@.default` <- function(object, name) base::`@`(object, name)
然而,这似乎不起作用,因为它破坏了S4方法的@
。我使用Matrix
包作为S4实例的示例:
Matrix::Matrix(1:4, nrow=2, ncol=2)@Dim
@. default
(Matrix::Matrix(1:4,nrow=2,nco=2),Dim)中的错误:这个类dgeMatrix的对象没有名称槽
如何实现一个通用的@
以便在S4类的情况下正确调度?
编辑
也对为什么这可能不是一个好主意的观点感兴趣?
R的留档对于@
是否已经是泛型有些混乱:@
的帮助页面说它是,但它没有列在内部泛型
页面上。
@
运算符具有特定的行为,并且(可能)是泛型的。从@
的帮助页面:“检查对象是S4对象(参见isS4),并且尝试在任何其他对象上使用@是错误的。”这似乎排除了为S3类编写方法的可能性,尽管留档不清楚此检查是发生在方法分派之前(如果有的话)还是之后(如果您为某些S3类提供了特定方法,则可以跳过它)。
您可以按照注释中的建议完全重新定义@
是什么来实现您想要的:
`@.default` <- function(e1,e2) slot(e1,substitute(e2))
但有两个理由不这样做:
1)一旦有人加载您的包,它就会取代普通的@
函数,因此如果人们使用其他S4对象调用它,他们将获得您的版本而不是R基本版本。
2)这个版本的效率比内部版本低得多,因为(1)你只是强迫你的用户使用它(除非他们使用繁琐的结构base::"@"(e1, e2)
)。效率可能对你的用例无关紧要,但对你的用户使用S4的其他代码可能很重要。
实际上,一个合理的妥协可能是定义您自己的二元运算符%@%
,并拥有默认方法调用@
。也就是说,
`%@%` <- function(e1,e2) slot(e1,substitute(e2))
setGeneric("%@%")
这在实践中称为:
> setClass("testClass",slots=c(a="character")) -> testClass
> x <- testClass(a="cheese")
> x %@% a
[1] "cheese"