我想学习R中的OO编程,作为练习,我要编写一小组用于读写Fortran名单的函数和方法。我是一个完整的菜鸟,所以请对下面的例子表示友好(你可以复制粘贴)。
我有以下类定义:
setClass("NamelistValue")
setClassUnion("NamelistValue", c("numeric", "character"))
setClass("Namelist",
representation(group = "character", variable = "character", value = "NamelistValue", comment = "character", file="character"),
prototype(group = NA_character_, variable = NA_character_, value = NA_real_, comment = NA_character_, file = NA_character_)
)
例如,这些替换数据的方法:
setMethod("[<-", c("Namelist", "character", "character", "NamelistValue"),
function (x, i, j, ..., value) {
if (length(i) > 1 | length(j) > 1) stop("Cannot subset with more than one index")
l <- which(x@group==i)
v <- which(x@variable[l]==j)
vals <- x@value
vals[l][v] <- value
initialize(x, group=x@group, variable=x@variable, value=vals, comment=x@comment, file="<None>")
}
)
setMethod("[<-", c("Namelist", "missing", "character", "NamelistValue"),
function (x, i=NULL, j, ..., value) {
if (length(i) > 1 || length(j) > 1) stop("Cannot subset with more than one index")
v <- which(x@variable==j)
vals <- x@value
vals[v] <- value
initialize(x, group=x@group, variable=x@variable, value=vals, comment=x@comment, file="<None>")
}
)
现在我设置了一个对象:
a <- new("Namelist", group="pippo", variable="ears", value=2, comment="Hi!")
让我们看一下使用showMethods(class = "Namelist")
的方法,这里是输出:
Function: [<- (package base)
x="Namelist", i="character", j="character", value="NamelistValue"
x="Namelist", i="missing", j="character", value="NamelistValue"
Function: initialize (package methods)
.Object="Namelist"
(inherited from: .Object="ANY")
看起来很好。现在我尝试用a[,"ears"] <- 4
替换某些值,命令失败:
Error in `[<-`(`*tmp*`, , "ears", value = 4) :
argument "i" is missing, with no default
但是,如果我再次尝试相同的命令再次成功 ...我从showMethods(class = "Namelist")
看到已经创建/继承了一些其他方法:
Function: [<- (package base)
x="Namelist", i="character", j="character", value="NamelistValue"
x="Namelist", i="missing", j="character", value="NamelistValue"
x="Namelist", i="missing", j="character", value="numeric"
(inherited from: x="Namelist", i="missing", j="character", value="NamelistValue")
Function: initialize (package methods)
.Object="Namelist"
(inherited from: .Object="ANY")
这是为什么?为什么它首先不起作用,但只在第二次尝试?我该如何解决这个问题?
答案 0 :(得分:0)
(我没有R的源代码,对于编辑此代码的人很高兴。[<-
是内部的,所以我看不到它的代码只是它的文档。)
内部泛型在调度方法之前会对它们自己进行一些检查,这包括评估签名中的所有参数(包括i
)。因此,您的第一次调用失败,因为i
没有默认值可以依赖(该方法尚未注册)。但是,默认方法足以注册S4方法,因此当退出调用时,方法已经注册。
通过在第一次通话之前和之后查看showMethods("[<-")
可以看出这一点。之后,尽管有错误,但它显示了继承的方法。
第二个调用有一个预先注册的方法,所谓的直接因为签名完全匹配。这看到了NULL
的默认值i
并根据需要使用了它,而[<-
的通用名称从未被调用过,因此我们不再看到错误。
我认为selectMethod
可能会以类似的方式注册方法而没有错误,但显然它没有。可能的解决方法可能是:
NamelistValue
(yuck!)使用显式""
而不是缺少参数:a["","ears"] <- ...
---这不会导致错误,副作用最小并注册必要的方法。麻烦的是你必须分别对字符和数字这样做:
a [“”,“ear”]&lt; - 4 a [“”,“ear”]&lt; - “ear!”
这应该涵盖所有继承的方法,但我很欣赏它并不理想......