如何从getClass(“MyClass”)或getRefClass(“MyClass”)返回的对象中访问定义S4引用类(参见?setRefClass)的实际源代码/表达式(因此在获取后,不是通过调查实际的源文件)?
我做过的功课
由于一切都是R中的对象,我可以检索源代码/表达式
1)通过简单地调查相应的对象来定期执行功能:
foo <- function(x) print(x) > foo function(x) print(x)
2)通过selectMethod获取特定方法的方法对象的形式方法:
setGeneric(name="myMethod", signature=c("x"), def=function(x) standardGeneric("myMethod") ) setMethod( f="myMethod", signature=signature(x="numeric"), definition=function(x) print(x) ) def <- selectMethod(f="myMethod", signature=c(x="numeric")) # Get actual source code/expression > attributes(def)$srcref function(x) print(x)
但S4参考类似乎有所不同:
setRefClass(Class="MyClass", fields=list(x.1="character")) def <- getRefClass("MyClass") # Inspect object >> no expression > def Generator object for class "MyClass": Class fields: Name: x.1 Class: character Class Methods: "callSuper", "copy", "export", "field", "getClass", "getRefClass", "import", "initFields", "show", "trace", "untrace" Reference Superclasses: "envRefClass" def.temp <- attributes(attributes(def)$.xData$def) # Inspect attributes >> no expression > attributes(def.temp) $names [1] "fieldClasses" "fieldPrototypes" "refMethods" "refSuperClasses" [5] "slots" "contains" "virtual" "prototype" [9] "validity" "access" "className" "package" [13] "subclasses" "versionKey" "sealed" "class" # Alternatively: > names(attributes(getClass("MyClass"))) [1] "fieldClasses" "fieldPrototypes" "refMethods" "refSuperClasses" [5] "slots" "contains" "virtual" "prototype" [9] "validity" "access" "className" "package" [13] "subclasses" "versionKey" "sealed" "class"
我似乎无法找到存储精确定义类的实际源代码/表达式的属性.
只是为了确保:这个表达式是我想要访问的
setRefClass(Class="MyClass", fields=list(x.1="character"))
背景/动机
我使用S4参考类(?setRefClass)工作很多,因此像class inheritance这样的OOP方面在我的日常工作中发挥了重要作用.我还遵循“一个def def per file”范例以保持组织有序,因此各种类defs存储在单独的文件中,其中文件名对应于各个类的名称.
与生活中的一切一样,这种方法也有一些优点,但也有一些固有的缺点:
方面1
无论是短期还是长期,您最终都会得到一个继承结构,该结构与各个源文件的字母顺序不再匹配.因此,简单地一个接一个地获取一个文件将导致在某个特定点处出现错误,其中某些必需的超类尚未被采购.
dir.create("classes", showWarnings=FALSE) write("setRefClass(Class=\"A\", contains=\"B\", fields=list(x.3=\"logical\"))", file="classes/class_A.R") write("setRefClass(Class=\"B\", contains=\"C\", fields=list(x.2=\"numeric\"))", file="classes/class_B.R") write("setRefClass(Class=\"C\", fields=list(x.1=\"character\"))", file="classes/class_C.R")
class_A.R是文件夹类中的第一个文件,但是为了获取它,我们首先需要获取class_B.R(因为这个文件定义了B类),这反过来需要C类,因此需要class_C.R的先前源.
因此,正确的整理是:
c("class_C.R", "class_B.R", "class_A.R")
方面2
对于某些任务,您确实需要/需要“每个文件多个defs”范例:quick&在进行并行化时,将必要的对象/函数/类轻松分发到工作进程,在实际构建包时组织代码等.
path <- "classes/classes.R" file.create(path) write("setRefClass(Class=\"C\", fields=list(x.1=\"character\"))", file=path, append=TRUE) write("setRefClass(Class=\"B\", contains=\"C\", fields=list(x.2=\"numeric\"))", file=path, append=TRUE) write("setRefClass(Class=\"A\", contains=\"B\", fields=list(x.3=\"logical\"))", file=path, append=TRUE)
广告方面1
我不喜欢保留某种手动整理参考来指定正确的采购订单的想法,因为我认为这是计算机可以轻松为我做的工作(找出正确的整理).你需要做的唯一事情是找出每个类的超类(它的依赖关系),然后检索正确的整理是一件小事.
编辑
如果有人感兴趣:我确实想出了一个有效的方法.如果您想查看一些代码,请给我留言.它基于解析(不评估)相应的类def源文件,以便研究列出超类的contains参数的值.然后对这些超类的源文件递归重复整个过程,直到最终得到正确的排序规则.这也不是那么费时.
这是大纲:
x <- list.files("classes", full.names=TRUE) code <- base::parse(file=x[1]) > code expression(setRefClass(Class="A", contains="B", fields=list(x.3="logical"))) superclasses <- eval(code[[1]][["contains"]]) > superclasses [1] "B" # Next: investigate source file for class 'B'
广告方面2
我也不喜欢手册和副本粘贴,所以我实现了一个例程,允许我合并存储在单个文件中或从相应对象中提取的源代码到单个“合并”文件(通过deparse(< source_code_expression>)并写入(…,append =真正)).对于类,正确的排序规则在这里也很重要,否则当您尝试获取合并文件时会再次出现错误.
对于这两个方面,能够选择如何获取类/函数/方法的实际源代码/表达式是很好的:
>或者根据调查存储在各自的代码
源文件(parse(file = *))
>或基于直接从中访问所需信息
各自的对象.
第二个选项是上述实际问题的链接.
命令的“源”代码未存储,因此您不会通过检查对象来查看它.通过在控制台输入并按[ENTER]来查看setRefClass的源代码.请注意,您所做的只是将参数传递给函数…未定义新表达式.所以,当你getRefClass时,你得到的是类知道自己的一切.
您可以通过创建parseRefClassArgs函数来重建它,该函数可以重建setRefClass的参数.