来自钱伯斯(出色)Extending R (2016):
一个有效性方法将从initialize()的默认方法中自动调用。推荐的初始化方法形式以callNextMethod()调用结尾,以确保可以在对类的生成器的调用中指定子类插槽。如果遵循此约定,则初始化将以对默认方法的调用结束,并且将在发生所有初始化之后调用有效方法。
我以为我理解了,但是我得到的行为似乎并不遵循这个约定。
setClass("A", slots = c(s1 = "numeric"))
setValidity("A", function(object) {
if (length(object@s1) > 5) {
return("s1 longer than 5")
}
TRUE
})
setMethod("initialize", "A", function(.Object, s1, ...) {
if (!missing(s1)) .Object@s1 <- s1 + 4
callNextMethod(.Object, ...)
})
A <- new("A", rep(1.0, 6))
A
# An object of class "A"
# Slot "s1":
# [1] 5 5 5 5 5 5
validObject(A)
# Error in validObject(A) : invalid class “A” object: s1 longer than 5
我希望通过在初始化方法的末尾添加callNextMethod()
来进行有效性检查。在validObject(.Object)
起作用之前添加一个显式的callNextMethod()
,但我在这里显然不明白。
显然,我也可以在有效性方法中进行所有相同的检查,但是理想情况下,所有有效性检查都将在setValidity
内进行,因此以后的编辑将放在一个地方。
略微更改initialize
函数会产生所需的结果-是否有理由使用一种方法而不是另一种方法?钱伯斯似乎更喜欢使用.Object@<-
,而我在其他地方也看到了以下方法(Gentlemman和Hadley)。
setMethod("initialize", "A", function(.Object, s1, ...) {
if (!missing(s1)) s1 + 4
else s1 <- numeric()
callNextMethod(.Object, s1 = s1, ...)
})
也许最好的指南来自initialize
本身-如果您检查默认方法的代码
getMethod("initialize",signature(.Object="ANY"))
然后您看到它确实确实包含对validObject
的显式调用:
...
validObject(.Object)
}
.Object
}
因此,如果您定义自己的initialize
方法,则最可能要做的就是在返回.Object
之前在方法末尾调用它。