我目前正在使用引用类编写包。我遇到过 阅读各种来源的问题:
Method initialisation in R reference classes
Can't reliably use RefClass methods in Snowfall
我收集是因为引用方法并非全部复制到每个对象 在课堂上,而不是在第一次访问时复制它们。
https://stat.ethz.ch/pipermail/r-devel/2011-June/061261.html
作为一个例子定义:
test <- setRefClass("TEST",
fields = list( a = "numeric"),
methods = list(
addone = function(){
a <<- a+1
},
initialize = function(){
a <<- 1
}
)
)
example <- test$new()
所以示例是类TEST
的新对象。在{中输入example$
和标签
控制台提供
> example$
# example$.->a example$.refClassDef example$.self
# example$a example$initialize
因此方法addone
不作为选项提供。它是可用的
但是打电话:
example$addone()
现在再次显示标签
# >
# > example
# Reference class object of class "TEST"
# Field "a":
# [1] 2
# > example$
# example$.->a example$.refClassDef example$.self
# example$a example$addone example$field
# example$initialize example$show
所以现在addone
和field
以及show
会显示为选项。
Martin Morgan建议在上述某个链接中强制定义方法。这个 运作良好
test <- setRefClass("TEST",
fields = list( a = "numeric"),
methods = list(
addone = function(){
a <<- a+1
},
initialize = function(){
a <<- 1
.self$addone #force definition
}
)
)
example <- test$new()
所以现在tabbing给出了:
# > example$
# example$.->a example$.refClassDef example$.self
# example$a example$addone example$initialize
我的一些课程有30多种方法,所以我想尽可能地做到这一点。 我已定义:
test <- setRefClass("TEST",
fields = list( a = "numeric"),
methods = list(
addone = function(){
a <<- a+1
},
initialize = function(){
a <<- 1
eval(parse(text=paste0('.self$',ls(test$def@refMethods))))
}
)
)
example <- test$new()
Tab键现在给出:
# > example$
# example$.->a example$.refClassDef example$.self
# example$a example$addone example$callSuper
# example$copy example$export example$field
# example$getClass example$getRefClass example$import
# example$initFields example$initialize example$show
# example$trace example$untrace
虽然这有效但感觉有点笨拙。另外使用test$def@refMethods
而不是getRefClass("TEST")$def@refMethods
感觉有点不对劲。有没有人以前处理过这个问题。
有没有更好的方法来解决问题?如果问题被过度提出,感谢任何建议和道歉。
答案 0 :(得分:6)
我想知道你的目标是什么?功能名称显示标签完成?然后,它需要一个功能请求到R-devel邮件列表的帖子。使用usingMethods
处理?setRefClass
时更加优雅地处理原始方案。持续的黑客可能是
initialize = function(...) {
methods <- getRefClass(class(.self))$methods()
eval(parse(text=paste0(".self$", methods)))
callSuper(...)
}
标签完成次数可以通过.DollarNames
包中的utils
自定义,所以
.DollarNames.TEST <- function(x, pattern)
grep(pattern, getRefClass(class(x))$methods(), value=TRUE)
也许可以在类层次结构的基础上编写S3方法吗?
答案 1 :(得分:3)
我知道这是一个老问题但在Google上搜索refClass标签时它仍然是最重要的条目,所以我只是添加更新:
不要像Martin建议的那样在.DollarNames函数中使用grep,而是使用utils包中的findMatches,因为它可以更好地与不同的Rgui一起使用(grep会在点击标签时删除部分键入的名称)
.DollarNames.TEST <- function(x, pattern){
utils:::findMatches(pattern, getRefClass(class(x))$methods())
}
这也是列表和data.frames
内部处理制表符的方式答案 2 :(得分:1)
@Martin Morgan指出,这被称为标签完成。包rcompletion
和更晚rcompgen
的任务是实现这一目标。他们现在已转移到utils
。
我查看了completion.R
的代码以及我可以确定的utils:::.DollarNames.environment
正在处理参考类的标签完成。
重新定义该功能似乎实现了标签完成:
assignInNamespace( x = ".DollarNames.environment",
function(x, pattern = "") {
y <- NULL
if(isS4(x) && !is.null(x[['.refClassDef']])){
if(.hasSlot(x$.refClassDef,'refMethods')){
y<-x$.refClassDef@refMethods
y<-ls(y, all.names = TRUE, pattern = pattern)
}
}
x<-ls(x, all.names = TRUE, pattern = pattern)
unique(c(x,y))
}
,ns = "utils")
有些注意事项:
我只会将它用于自己的用途。目前我正在调试和记录包。我有一些冗长的方法名称,无法准确记住它们是什么,因此标签完成将有很大帮助。
不赞成在包中使用assignInNamespace
(如果没有禁止)请参阅?assignInNamespace
。
强制定义方法更为可取。