3

假设有两个包。

Package_A 有这个类:

setClass("Person", 
         slots = c(
           name = "character", 
           age = "numeric"
         )
)

setGeneric("age", function(x) standardGeneric("age"))
setMethod("age", "Person", function(x) x@age)

Package_B 有一个类似的类:

setClass("Person", 
         slots = c(
           name = "character", 
           age = "numeric"
         )
)

setGeneric("age", function(x) standardGeneric("age"))
setMethod("age", "Person", function(x) x@age * 10) # notice the difference here

所以用户已经在他们的工作环境中加载了这两个包:

library(Package_A)
library(Package_B)

在这个用户的工作环境中,R 如何解决创建“Person”对象的困惑:

john <- new("Person", name = "John Smith", age = 7)

在此用户的工作环境中,R 如何解析调用正确的方法:

age(john)
4

1 回答 1

0

访问特定包中的类

getClass()

new()接受一个classRepresentation对象,您可以使用getClass. 例如,new(getClass('className', where='packageName'))。但是,请注意,如果您还没有导入包,并且您已经定义了一个具有相同名称的新类,这将不起作用。我在这里演示这个问题:

install.packages('lookupTable')
setClass('lookupTable', slots = c(notworking='numeric'))
new(getClass('lookupTable', where='lookupTable'))
#> An object of class "lookupTable"
#> Slot "notworking":
#> numeric(0)

(它打印了“notworking”插槽,这意味着它正在实例化我的自定义类,而不是正确的包版本)

new(classNameWithAttribute)

有一个奇怪但记录在案的功能new,它允许您package在类名上设置属性,这实际上工作得很好(即没有上面提到的问题),如果有点冗长:

name = 'className'
attr(name, 'package') = 'packageName'
new(name)

不过,您没有理由不能将其变成可重用的功能:

new = function(cls, pkg, ...){
    attr(cls, 'package') = pkg
    methods::new(cls, ...)
}
new('className', 'packageName')

良好的包装设计

当然,如果 S4 类的打包器提供以下两种机制之一,则所有这些都可以避免:

导出setClass()

setClass()既有副作用(将类存储在注册表中),也有返回值(类生成器函数)。因此,如果打包者选择在他们的 中存储和导出返回值NAMESPACE,我们可以稍后访问它:

# In package "myPackage"
myClass = setClass('myClass')

# In package's NAMESPACE
export(myClass)

# In user's script
new(myPackage::myClass)

例如,您可以使用与之前相同的测试包进行测试:

install.packages('lookupTable')
new(lookupTable::lookupTable)

导出构造函数

这是生物导体的标准做法。他们定义了一个与类本身同名的构造函数。然后,您可以使用 访问构造函数::,并调用它而不是new

install.packages("BiocManager")
BiocManager::install("IRanges")

new("IRanges")
# Equivalent to 
IRanges::IRanges()
于 2021-03-30T13:25:21.003 回答