如何解决扩展 S4 classes 的 R 包中的警告消息(未找到元数据对象;SpatialLinesNULL class 未导出)

How to resolve warning messages (metadata object not found; SpatialLinesNULL class not exported) in my R package which extends S4 classes

这是我在 Whosebug 上的第一个问题 post,所以请更正我犯的任何协议错误。但是我已经从网站上许多其他问题的答案中受益匪浅,所以在我继续之前,我想感谢为网站做出贡献的社区

概述

我在 Windows 7 机器上使用 R、RStudio 和软件包 devtoolsroxygen2(问题末尾完整 session_info

我正在尝试编写自己的包,它定义了包 sp 中 S4 class SpatialLines 的子 classes,并且还使用包裹 rgeos。当我使用 devtools 到 documentload_all我的包裹。

警告信息

第一条消息是

class "Spatial" is defined (with package slot ‘sp’) but no metadata object found to revise subclass information---not exported?  Making a copy in package ‘minweSpatialNULL’ 

当我解决这个问题时,通过在 NAMESPACE 文件中添加一个条目(没有完全理解为什么它是必要的),然后对 DESCRIPTION 文件进行进一步的更改,我收到了第二条消息,这让我被打败了,到目前为止.

d> devtools::document()
Updating minweSpatialNULL documentation
Loading minweSpatialNULL
Error: class "SpatialLinesNULL" is not exported by 'namespace:rgeos'

我尝试过的,以及我留下的问题

我用谷歌搜索并搜索了几个网站寻找提示,但我找到的最接近的是 2011 年 12 月的一个简短线程,询问 SpatialLinesNULL 来自哪里 --- 到哪个 答案是 rgeoshttp://lists.r-forge.r-project.org/pipermail/rspatial-devel/2011-December/000033.html

我已经尝试尝试了解自己的问题所在,并采取了步骤 通过调试器中的代码直到我迷路,比我能理解的更深入 足以弄清楚应该发生什么。进行中 已经产生了一个小的(不是)工作示例,如下所示。

我有 3 个问题。它们在这里进行了总结,但只有在我下面的(不是)工作玩具示例的上下文中才真正有意义:

代码示例

我的玩具工作示例的 r 代码(仅删除了 roxygen 注释以保存 space) 是:

MyClass1 <- setClass('MyClass1', contains = c('SpatialLines'))
MyClass2 <- setClass('MyClass2', contains = c('MyClass1'))

MyClass2 第二代子class 似乎很重要(没有它警告消失)。我不明白为什么。

我对这段代码进行了运行一系列测试,使用devtoolsroxygen2。测试因 NAMESPACE 文件中的内容以及 在 DESCRIPTION 文件的 Imports 指令中。执行测试包括在 RStudio 中 运行ning devtools::load_all()(或 devtools::document() 一路调用 load_all())。出现的警告消息已在上面 post 编辑。我在每次测试之间的干净全局环境中重新启动我的 R 会话(警告仅在我 运行 load_alldocument 第一次出现时出现)。

在跟进下面给出的答案时,我意识到我也应该尝试使用 R 从 shell 命令行构建和安装我的玩具包。

测试1

test1 有 DESCRIPTION 文件条目(完整的 DESCRIPTION 文件见本题末尾):

Imports:
    methods,
    sp

完整的 NAMESPACE 文件(由上面省略的 roxygen 注释生成)是:

# Generated by roxygen2 (4.1.0.9001): do not edit by hand

importClassesFrom(sp,SpatialLines)
importFrom(sp,SpatialLines)

尝试运行devtools::load_all()(或devtools::document()) 重新启动的 R 会话生成第一个警告(如上所示)。

问题 1 为什么 R 需要 ~~(virtual?)~~ superclass Spatial 无论如何,为什么只有当我有我的代码中定义了第 2 代 MyClass2已添加说明 我原以为 R 包装名称space 机制会处理任何查找和访问前因/超级classes 的需要 classes =36=]编辑了我实际使用的class。

测试2

test2 通过更新 NAMESPACE 文件解决了 问题 警告信息。没有进行其他更改。

当完整的 NAMESPACE 文件为 :

时警告消失
# Generated by roxygen2 (4.1.0.9001): do not edit by hand

importClassesFrom(sp,Spatial)
importClassesFrom(sp,SpatialLines)
importFrom(sp,SpatialLines)

测试3

当我对 DESCRIPTION文件中的Imports指令,即加入rgeos。这是从 test2 创建 test3 场景所做的唯一更改。

Imports:
    methods,
    sp,
    rgeos

现在我收到一条警告,看起来像来自 test1 的问题,即:

class "SpatialLinesNULL" is defined (with package slot ‘rgeos’) but no metadata object found to revise subclass information---not exported?  Making a copy in package ‘minweSpatialNULL

据我所知,SpatialLinesNULL 是一个新的 Spatial 的 superclass,在 rgeos 中定义,因此它可以提供一些 通用函数和方法。

问题 2 我假设无论我的第一条警告消息是什么原因,也是这条类似消息的原因。
我在正确的轨道上吗?

测试4

在 test4 中,我尝试在 test2 中应用与 worked 相同的解决方案,即将 missing 条目添加到 NAMESPACE 文件中。这是 test4 的完整命名空间文件。

# Generated by roxygen2 (4.1.0.9001): do not edit by hand

importClassesFrom(rgeos,SpatialLinesNULL)
importClassesFrom(sp,Spatial)
importClassesFrom(sp,SpatialLines)
importFrom(sp,SpatialLines)

我在哪个阶段收到最终错误消息:

d> devtools::document()
Updating minweSpatialNULL documentation
Loading minweSpatialNULL
Error: class "SpatialLinesNULL" is not exported by 'namespace:rgeos

在这个阶段我卡住了。

问题3是test3的警告和这个 随后的错误我可以自己解决(如果是这样的话)? 或者我需要问 rgeos 包的维护者 寻求帮助(例如要求他们导出 SpatialLinesNULL)?

session_info(来自测试4)

d> devtools::session_info()
Session info --------------------------------------------------------------------------
 setting  value                       
 version  R version 3.1.2 (2014-10-31)
 system   x86_64, mingw32             
 ui       RStudio (0.98.953)          
 language (EN)                        
 collate  English_Australia.1252      
 tz       Australia/Sydney            

Packages ------------------------------------------------------------------------------
 package          * version    date       source        
 devtools         * 1.7.0.9000 2015-02-20 local         
 lattice          * 0.20-29    2014-04-04 CRAN (R 3.1.2)
 minweSpatialNULL * 0.0.0.9000 <NA>       local         
 Rcpp             * 0.11.4     2015-01-24 CRAN (R 3.1.2)
 rgeos            * 0.3-8      2014-09-21 CRAN (R 3.1.2)
 roxygen2         * 4.1.0.9001 2015-02-21 local         
 rstudio          * 0.98.953   2014-08-02 local         
 rstudioapi       * 0.2        2014-12-31 CRAN (R 3.1.2)
 sp               * 1.0-17     2015-01-08 CRAN (R 3.1.2)
 stringr          * 0.6.2      2012-12-06 CRAN (R 3.1.1)
d>

test4 的完整文件

R/myclasses.r

#------------------------------------------------------------------------------
#' MyClass1
#' 
#' A subclass of SpatialLines
#' 
#' MyClass1 is a subclass of sp::SpatialLines.
#' @importClassesFrom sp SpatialLines Spatial
#' @importFrom sp SpatialLines
#' @importClassesFrom rgeos SpatialLinesNULL
MyClass1 <- setClass('MyClass1', contains = c('SpatialLines'))

#------------------------------------------------------------------------------
#' MyClass2
#' 
#' A subclass of MyClass1
#' 
#' MyClass2 is a subclass of MyClass1 and a 2nd generation subclass of
#' sp::SpatialLines.
#' @importClassesFrom sp SpatialLines
MyClass2 <- setClass('MyClass2', contains = c('MyClass1'))

描述文件

Package: minweSpatialNULL
Title: Minimum Example of my Problem with SpatialLinesNULL
Version: 0.0.0.9000
Authors@R: person("Geoff", "Lee", , "geoff.lee@gmail.com", role = c("aut", "cre"))
Description: (Hopefully) demonstrates my problem with warnings
  that I cannot seem to eradicate. 
Depends: R (>= 3.1.2)
Imports:
    methods,
    sp,
    rgeos
License: GPL (>= 2.0)
LazyData: true

名称空间文件

# Generated by roxygen2 (4.1.0.9001): do not edit by hand

importClassesFrom(rgeos,SpatialLinesNULL)
importClassesFrom(sp,Spatial)
importClassesFrom(sp,SpatialLines)
importFrom(sp,SpatialLines)

结论

非常感谢您提供的任何帮助、建议或指导!即使这只是关于我如何提出更好的问题:-)

感谢您提出这个广泛的问题。我有两个建议来改进它。首先,提供一个可重现的示例,在这种情况下,它是一个最小的包,可以让我们重现您的警告或错误消息。例如,

MyClass1 <- setClass('MyClass1', contains = c('SpatialLines'))
MyClass2 <- setClass('MyClass2', contains = c('MyClass1'))

在加载了 sp 的会话中工作正常,但是在您的包代码中执行此操作时出现了您遇到的问题。创建这样一个包意味着要做很多猜测工作:我们没有看到你的完整 NAMESPACE,所以不知道你导出了什么,并且希望在加载你的包后在 R 会话中工作。第二:将您的问题与使用 devtools 引起的问题区分开来(即,使用构建和安装包的标准 R 包开发术语)。

根据你提供的,我只能回答:

  • Q1:Spatial 不是虚拟的 class,它之所以存在是因为它定义了所有派生的 classes 的共同点(CRS 和边界框),它是必需的,因为为它定义了对所有派生的 classes 进行操作的方法。 MyClass2需要它与你的包裹有关,我没有
  • Q2:我无法回答,因为您没有显示导致 Q1 的警告。此外,SpatialLinesNULL 不是 Spatial 的超 class,而是 SpatialLines 的超 class,由

    定义

    setClassUnion("SpatialLinesNULL", c("SpatialLines", "NULL"))

  • 问题 3:您可以尝试编译导出此 class 的 rgeos 的修改版本;如果您提供了一个好的用例(重现您的问题的最小包),rgeos 的开发人员之一将对其进行调查。

此答案汇集了我所了解的与我提出的一系列问题相关的所有信息,以供遇到类似问题的任何其他人受益。

事实证明,按照问题提出的顺序倒序呈现答案更容易。

真正解决我的具体问题的方面是由@Edzer Pebesma 提供的 - 感谢他。

John Chambers 回答了我在 r-devel 邮件列表中提出的更具体的后续问题,这确实帮助填补了我对为什么会发出警告消息的理解上的空白 - 我也非常感谢他的指导和帮助。

以下解释中的任何错误完全是我自己的!

The test4 version of the toy package referenced in this question and answer used to be found in --> folder SpatialLinesNULL of branch SpatialLinesNULL in a github repo at http://github.com/Geoff99/Examples/tree/SpatialLinesNULL <-- Other versions of the test sequence can be constructed by deleting a line or two from the NAMESPACE and DESCRIPTION files.

Update 6 May 2017 - test4 version code moved to a gist at https://gist.github.com/Geoff99/29be25bce4cd4c918921bf68769c6a39

问题 3(test4 之后)

Is the warning from test3 and this subsequent error something I can resolve myself (if so how)? or do I need to ask the maintainer of the rgeos package for help (eg ask them to export SpatialLinesNULL)?

来自 test3 的警告是

class "SpatialLinesNULL" is defined (with package slot ‘rgeos’) but no metadata object found to revise subclass information---not exported?  Making a copy in package ‘minweSpatialNULL

来自 test4 的错误消息是

d> devtools::document()
Updating minweSpatialNULL documentation
Loading minweSpatialNULL
Error: class "SpatialLinesNULL" is not exported by 'namespace:rgeos

最好的解决方案是联系 rgeos 包的维护者,并要求他们导出警告和错误消息中提到的丢失的 SpatialLinesNULL class。 Edzer Pebesma 为我解答了这个问题,还对 rgeos 包进行了必要的更新,对此我深表感谢。安装升级版包 rgeos 后,我只需将 importClassesFrom(rgeos,SpatialLinesNULL) 添加到玩具包的 NAMESPACE 文件中,警告就消失了。

如果您使用不同的软件包遇到类似情况,那是我推荐的策略。

怀疑 我可以自己解决这个问题(主要是通过手动复制命名空间环境中有关 SpatialLinesNULL class 的缺失元数据我的包,这基本上就是 methods 包在发出警告后自己做的事情)---但它是如此混乱 hack 我将不解释如何.如果您真的需要在将来的某个阶段执行此操作,问题 1(下方)的答案收集了我需要了解的信息,以弄清楚如何执行 hack.

问题2(test3之后)

I am presuming that whatever the reason is for my first warning message, is also the reason for this similar message. Am I on the right track?

来自 test3 的警告是

class "SpatialLinesNULL" is defined (with package slot ‘rgeos’) but no metadata object found to revise subclass information---not exported?  Making a copy in package ‘minweSpatialNULL

来自 test1 的第一个警告是

class "Spatial" is defined (with package slot ‘sp’) but no metadata object found to revise subclass information---not exported?  Making a copy in package ‘minweSpatialNULL’ 

答案是,两条消息出现的原因相同。

警告消息均由名为 .findOrCopyClass 的函数生成,该函数是方法包中的内部函数(即 non-exported)。要查看此函数的代码,必须使用 ::: 运算符。在 R 控制台中输入 methods:::.findOrCopyClass。 (这需要加载方法包,几乎总是如此)。 .findOrCopyClass 在找不到定义 class 的 元数据 时发出此警告,因此它必须复制元数据。

请参阅下文了解 元数据 是什么,为什么它需要包含在我的玩具包的命名空间中,以及(我的最佳猜测)为什么发出此警告。

.findOrCopyClasssetIs 调用,它是 methods 包的导出函数。 setIs 又被方法函数 setClass 调用(多次),我在我的玩具包装示例中调用了它。键入 ?setIs?setClass 以获得有关这些函数的更多信息。或者,如果您想查看其源代码,只需在 R 控制台中键入 setIssetClass

问题 1(test1 之后)

Why does R need the ~~(virtual?)~~ superclass Spatial anyway~~, and why only when I have the 2nd generation MyClass2 defined in my code~~?

Clarification added : I had thought that the R packaging namespace mechanism would have taken care of any need to find and access antecedents / superclasses once I had @importClassesFromed the class I actually use.

先致歉和更正。

  • 原题问的部分:

    and why only when I have the 2nd generation MyClass2 defined in my code?

    完全错了。尽管我在发布问题之前进行了检查,但我一定在不知不觉中在我的 globalenv() 中缓存了一些隐藏信息。即使我的玩具包中只定义了 MyClass1,潜在的问题仍然存在。

  • Spatial 不是虚拟 class。 SpatialLinesNULL 虚拟 class。 superclass 是否是虚拟的与此问题无关。

  • 这个问题与
    • 定义超级class的地方(在我的玩具示例中,Spatial来自spSpatialLinesNULL来自rgeos
    • superclass 定义是否从那个包导出(在玩具示例中,sprgeos
    • ,因此 R 在检查和安装使用 class(例如 SpatialLines) 其 parents 包括超级 classes (eg Spatial, SpatialLinesNULL).

缺少元数据 警告消息是关于什么的

以下是 methods 包文档的部分注释说明。我花了一段时间才掌握,但这与我开始时的知识基础不高有关。该文档非常有用,如果您了解了这一点,我建议您阅读它。我发现 ?setClass?Classes?getClassDef?classMetaName?setIs 中的条目特别有价值。

setClass 做什么

来自 ?setClass 文档(强调由我添加):

Create a class definition, specifying the representation (the slots) and/or the classes contained in this one (the superclasses), plus other optional details. As a side effect, the class definition is stored in the specified environment. A generator function is returned as the value of setClass(), suitable for creating objects from the class if the class is not virtual.

methods:::.findOrCopyClass发出的警告信息与class定义的创建和存储有关。 class 定义是(或存储在?)元数据 object.

什么是 元数据 object

来自 ?Classes 文档:

Class definitions are objects that contain the formal definition of a class of R objects, ... and

When a class is defined, an object is stored that contains the information about that class. The object, known as the metadata defining the class, is not stored under the name of the class (to allow programmers to write generating functions of that name), but under a specially constructed name. To examine the class definition, call getClass. The information in the metadata object includes:

  • Slots ...
  • SuperClasses ...
    • The information about the relation between a class and a particular superclass is encoded as an object of class SClassExtension. A list of such objects for the superclasses (and sometimes for the subclasses) is included in the metadata object defining the class
  • Prototype ...

methods 包是关于创建和管理这些元数据 objects(对于 S4 classes,对于旧的 S3 class也是)。

新 class(例如 MyClass1)的元数据 object 包括有关其定义中任何插槽的信息(因为 MyClass1 指定 contains = c('SpatialLines') 它从 SpatialLines class 继承所有插槽,在包 sp 中定义)。

重要的是,class 的元数据 object 必须 包含有关任何超级 class 的信息 - 否则新的怎么可能class 曾经从其 parent 继承任何东西,即超级 class 吗?一种方式和另一种方式,关于 superclasses 的信息必须一直到达继承树。在示例中,MyClass1 的距离为 1 superclass SpatialLines,因此继承了 SpatialLines 的所有更远的祖先,无论他们是谁。

  • 我想我在某处读过,但是放错了 link,元数据 object 可以处于两种状态 - 不完整或完整。在不完整状态下,新 class(例如 MyClass1)的 superclasses 列表可能(还)没有在继承链上一直被填充,而通过当使用 class 定义时,R 必须遍历继承链,并为 class 填写完整的 genealogy。当检查或安装包时,继承链必须是完整的 - 如果之前没有完成,则必须在 install.packages 步骤中。
如何查看元数据 object

使用getClassgetClassDef查看给定class的元数据object。

文档 ?getClass?getClassDef 解释了 R 在哪些环境中搜索元数据 object。需要注意的关键是,必须 至少 加载一个包,然后才能找到包中定义的来自 classes 的元数据 object。

这是我的玩具包 (minweSpatialNULL) 中的一些示例,在它加载了 rgeos 的 0.3-9 版本后,它确实导出了 SpatialLinesNULL class.请注意:

  • MyClass1知道它所有的parent超classes(通常情况),并且
  • SpatialLinesNULL(这是在rgeos包中定义的Class Union)知道几乎它的所有children subclasses,即使rgeos本身对MyClass1一无所知或 MyClass2 !

    d> getClass('MyClass1')
    Class "MyClass1" [package "minweSpatialNULL"]
    
    Slots:
    
    Name:        lines        bbox proj4string
    Class:        list      matrix         CRS
    
    Extends: 
    Class "SpatialLines", directly
    Class "Spatial", by class "SpatialLines", distance 2
    Class "SpatialLinesNULL", by class "SpatialLines", distance 2
    
    Known Subclasses: "MyClass2"
    
    
    d> getClass('SpatialLinesNULL')
    Extended class definition ( "ClassUnionRepresentation" )
    Virtual Class "SpatialLinesNULL" [package "rgeos"]
    
    No Slots, prototype of class "NULL"
    
    Known Subclasses: 
    Class "NULL", directly
    Class "SpatialLines", directly
    Class ".NULL", by class "NULL", distance 2, with explicit coerce
    Class "SpatialLinesDataFrame", by class "SpatialLines", distance 2
    Class "MyClass2", by class "MyClass1", distance 3
    d> 
    
  • 其实有点好奇 SpatialLinesNULL 知道 MyClass2 因为它是 MyClass1 的子 class,但是 not 似乎直接提到了 MyClass1 本身。我还没弄明白为什么。

为什么 superclasses 的列表可以改变

我困惑了一会儿,为什么我的玩具 MyClass1 class 的 superclasses 列表发生了变化,而我除了添加 [= =19=] 到玩具包描述文件中的 Imports 指令。

原因是methods包非常巧妙。除了定义 subclasses 之外,还可以将 parent superclasses 插入到一个 class, 之后 class 已经被定义。

一个简单的方法是使用setClassUnion(键入?setClassUnion 以获得解释)。这就是 rgeos 在定义 SpatialLinesNULL 时所做的 - 它为 SpatialLines 创建了一个新的 parent。这就是为什么当我在我的玩具包 DESCRIPTION 文件中添加 rgeos 条目时,class MyClass1 突然也获得了另一个超级 class。在交互式设置中,可能会发生类似的事情,这取决于我是否加载(或附加并加载)rgeos 包。

还有一种更复杂的方法可以在事后添加祖先 - 请参阅 ?setIs

元数据的名称 objects

与所有其他 object 一样,R 通过名称查找元数据 object。如果在包中定义了 object,则 object 的名称位于

  • 包的命名空间环境(例如environment: namespace:minweSpatialNULL),或
  • 包的导入环境(例如environment: imports:minweSpatialNULL)。

再次来自 ?Classes 文档:

When a class is defined, an object is stored that contains the information about that class. The object, known as the metadata defining the class, is not stored under the name of the class (to allow programmers to write generating functions of that name), but under a specially constructed name.

您可以使用方法包提供的 classMetaName 函数找到专门构造的名称 - 详情请参阅 ?methods::classMetaName

元数据 object 的 名称 的示例是:

d> classMetaName('MyClass1')
[1] ".__C__MyClass1"

因为前导 . 这个元数据的名称 object (即 .__C__MyClass1)通常在你 ls 包的命名空间环境时被隐藏 - 但是您可以使用 lsall.names = TRUE 参数来查看它。

d> # Recall that MyClass1 is the name I chose for the generator function 
d> #  returned by setClass when I defined the class MyClass1
d> env_toy_package <- environment(MyClass1)
d> ls(env_toy_package, all.names=TRUE)
[1] ".__C__MyClass1"       ".__C__MyClass2"       ".__DEVTOOLS__"       
[4] ".__NAMESPACE__."      ".__S3MethodsTable__." ".packageName"        
[7] "MyClass1"             "MyClass2"            
d> 

并且如果您查看包命名空间环境(即 imports:minweSpatialNULL 命名空间环境)的 parent.env,您会发现 [= 的超级 classes 的隐藏名称41=],这正是 .findOrCopyClass 正在寻找的,所以它们可以放在那里!

d> parent.env(env_toy_package)
<environment: 0x0000000008df59d8>
attr(,"name")
[1] "imports:minweSpatialNULL"

d> ls(parent.env(env_toy_package), all.names = TRUE)
[1] ".__C__Spatial"          ".__C__SpatialLines"     ".__C__SpatialLinesNULL"
[4] "library.dynam.unload"   "SpatialLines"           "system.file"           
d> 
最后,'.findOrCopyClass`警告是关于什么的

.findOrCopyClass发出警告时,例如:

class "Spatial" is defined (with package slot ‘sp’) but no metadata object found to revise subclass information---not exported?  Making a copy in package ‘minweSpatialNULL’ 

该函数让我知道它无法在它搜索的名称空间中找到 隐藏 名称 .__C__Spatial 并修改 object 该名称绑定到的。它知道隐藏名称 应该 在哪里 --- 它必须来自包 sp,因为元数据 object 来自 SpatialLines class 本身说它的 parent superclass (Spatial) 住在哪里。元数据 object 中祖先 superclass 的完整规范包括一个 package 属性,其中包含定义祖先 superclass 的包的名称,just 以防两个现有的加载包恰好为 class 选择了相同的名称!

这就是 importClassesFrom 丢失的超级 class 起作用的原因 - 它将丢失的 hidden 名称带入 imports:minweSpatialNULL 环境minweSpatialNULL 玩具包,.findOrCopyClass 可以从中找到它们,并在必要时更新它们。

为什么 .findOrCopy 发出警告

我想知道为什么 .findOrCopyClass 告诉我它找不到元数据 object,而接下来它说的是它正在我的包命名空间中制作副本!我在 r-devel 邮件列表中提出了这个问题,John Chambers 亲切地为我回答了这个问题(重点是我添加的):

the purpose of finding the class definition is to update the entry for the new relationship, as the warning message suggests. That requires that the namespace holding the definition be writable.

In the case of subclass information, the original namespace is very likely to be locked, if it's not the package currently being loaded. Copying the definition in order to update subclass information seems the only reasonable choice, and no warning message is needed.

A revised version will omit this message.

我剩下的概念性问题与 object 的 name(例如函数或 class(将是准确地说,一个函数 object 或一个 class 元数据 object)) 以及 object 本身发生了什么。或者换句话说,是否需要更新命名空间(可能已锁定),或者 object 本身的(状态)是否需要更新。

事实证明,'findorCopyClasses 并不是抱怨它找不到 (non-exported) superclass,而是它找不到它 in可以改变 superclass 值的地方.

锁定是什么意思

?base::bindenv 文档说:

" The namespace environments of packages with namespaces are locked when loaded."

锁定环境意味着

" prevents adding or removing variable bindings from the environment. Changing the value of a variable is still possible unless the binding has been locked"

但是一些实验揭示了这个以及包命名空间 environments 被锁定,imports:namespace 中的 bindings 被锁定。锁定绑定意味着:

" The value of a locked binding cannot be changed".

因此,由于 superclass 元数据 object 来自另一个包(例如 rgeos),它在另一个包的命名空间中的绑定被锁定,因此它的值无法更改。或者就示例而言,当方法包想要将 Myclass1MyClass2 添加到 subclasses 的列表时 SpatialLinesNULL 'owns',它发现不能,因为SpatialLinesNULL的绑定(或者准确地说,隐藏名称.__C__SpatialLinesNULL的绑定)被锁定了。因此,关于需要制作副本的消息!

复制 的替代方法可能 是暂时解锁其他包的名称空间中的绑定,更新 object,然后重新锁定绑定 - 但因为我有刚刚了解了锁定环境和绑定,我不知道这可能会带来什么后果。我会一个人呆着的。

好的,如果未导出所需的 superclass,如何 hack 解决方案

警告 我还没有测试这么多,无论如何这是一个 糟糕的 想法,但如果你真的非常渴望得到警告消息消失...

第一步。查看警告消息并找到丢失的 superclass 的(文本)名称及其来源的包。

第二步。使用 classMetaName 找到丢失的未导出的 superclass 的隐藏和损坏的名称。对于 superclass MissingSuperclass 它可能是 .__C__MissingSuperclass

第三步。在调用之前,使用 ::: 方法访问元数据 object(即 donorpackage:::.__C__MissingSuperclass)并在属于您的包的适当环境中为其指定适当的名称(即 .__C__MissingSuperclasssetClass 创建您自己的 class。

正如我已经说过的,这确实是一个 糟糕的 想法,因为搬起石头砸自己的脚很容易,何必呢,因为这本质上是.findOrCopyClasssetIs 在警告消息发送后似乎做了什么。

结束

如果您已经读到这里,希望对您有所帮助!我已经写了这么长的篇幅,主要是作为未来我的教程:-)