查找 S4 class 对象的包或命名空间名称

Find package or namespace name of a S4 class object

给定一个已在 R 包中定义的 S4 class 对象:

如何可靠地找出 S4 对象的包名称(名称空间)?

# Create a class in the global env
MyS4Class <- setClass("MyS4Class", slots = c(name = "character"), prototype = list(name = "unknown"))
class(MyS4Class)
# [1] "classGeneratorFunction"
# attr(,"package")
# [1] "methods"

obj <- new("MyS4Class")
class(obj)
# [1] "MyS4Class"
# attr(,"package")
# [1] ".GlobalEnv"

# Get an instance of a S4 class from a package    
library(odbc)
obj2 <- odbc::odbc()
# isS4(obj2)
# [1] TRUE
class(obj2)
# [1] "OdbcDriver"
# attr(,"package")
# [1] "odbc"

看起来 package 属性总是填充命名空间名称,但这是意外还是设计?

PS: 包名可以通过attr(class(obj2), "package")

照常提取

这是设计使然。来自 Section 1.12.1 of the R Internals Manual:

S4 objects are created via new() and thence via the C function R_do_new_object. This duplicates the prototype of the class, adds a class attribute and sets the S4 bit. All S4 class attributes should be character vectors of length one with an attribute giving (as a character string) the name of the package (or .GlobalEnv) containing the class definition.

我们可以放心,S4 对象的 class 属性将具有包属性,尽管从技术上讲包属性的值可能不正确。查看 R_do_new_object here 的 C 代码,无论何时创建 S4 对象,都会按照 class 定义中的定义设置 class 属性。查看 setClass 的 R 代码(以及它调用的函数 makeClassRepresentationassignClassDefclassGeneratorFunction),将始终分配包属性,尽管默认值(这就是您所追求的)在技术上可以自定义指定为 setClass() 的参数;来自 help("setClass"):

package: supplies an optional package name for the class, but the class attribute should be the package in which the class definition is assigned, as it is by default.

假设在定义 class 时正确指定,或者在定义 class 时未指定(在这种情况下,默认值将提供正确的值),您应该能够使用 class().

可靠地获取包名称