假设我正在开发一个名为foo的软件包,该软件包想使用description软件包中的memisc函数。我不想导入整个memisc命名空间,因为:

  • 不好
  • memisc覆盖了基本的aggregate.formula函数,该函数破坏了几件事。例如,example(aggregate)会惨败。

  • 该软件包包括以下文件:

    说明
    Package: foo
    Version: 0.0
    Title: Foo
    Imports:
        memisc
    Collate:
        'foo.R'
    

    NAMESPACE
    export(bar)
    importFrom(memisc,description)
    

    R / foo.R
    ##' bar function
    ##'
    ##' @param x something
    ##' @return nothing
    ##' @importFrom memisc description
    ##' @export
    
    `bar` <- function(x) {
        description(x)
    }
    

    我认为使用importFrom不会加载整个memisc命名空间,而只会加载namespace::description,但事实并非如此。从 Vanilla R开始:
    R> getS3method("aggregate","formula")
    ## ... function code ...
    ## <environment: namespace:stats>
    R> library(foo)
    R> getS3method("aggregate","formula")
    ## ... function code ...
    ## <environment: namespace:memisc>
    R> example(aggregate)
    ## Fails
    

    因此,您知道我如何从description导入memisc函数而又不会在我的环境中获取aggregate.formula吗?

    最佳答案

    你不能

    如果在memisc字段中声明Imports:,则在加载包时将加载 namespace ,并且包可以找到导出的对象。 (如果您在Depends:中指定它,则将命名空间加载并附加到搜索路径中,这使得导出的对象可由任何代码均可找到。)

    加载 namespace 的一部分是向泛型注册方法。 (我看过但找不到这样的规范文档;我将呼吁在NAMESPACE文件中将函数声明为S3方法作为证据这一事实。)定义的方法与泛型一起保存,并具有可见性。通用函数(或通用函数的 namespace )。

    通常,程序包将为其创建的泛型或其定义的类定义方法。 S3对象系统没有用于正式定义S3类(或哪个包创建了该类)的机制,但是一般的想法是,如果该包定义了返回具有该类属性的对象的函数(并且是唯一的包,确实),该类就是该包的类。如果这两个条件之一成立,将不会有问题。如果在包中定义了泛型,则只有在连接了包后才能找到它;如果在包中定义了该类,则只有在附加并使用了该包的情况下,该类的对象才会存在(并因此被分派(dispatch))。

    memisc示例中,都不成立。在aggregate包中定义了stats泛型,在formula包中也定义了stats对象(基于该包定义了as.formula[.formula等)。由于它既不是memisc的泛型也不是memisc的对象,所以效果可以如果只加载memisc但未附加reorder.factor,甚至可以看到(和分派(dispatch)到的方法)。

    有关此问题的另一个示例,但带有memisc::describe,请参见Reordering factor gives different results, depending on which packages are loaded

    通常,将方法添加到泛型中而不是软件包不能控制对象或泛型的方法不是一个好习惯。如果它覆盖了核心程序包中的方法,则加倍;如果它不是核心程序包中现有功能的向后兼容功能,那就太糟糕了。

    对于您的示例,将ojit_code的代码复制到您的包中可能会更好,尽管这种方法有其自身的问题和警告。

    10-07 20:20