我正在尝试创建一个包含另一个具有可选插槽的类 A 的类 B(即使在定义类 A 时没有传递任何参数,也应该创建该对象):
定义A类并创建实例时,有效性测试没问题(检测空槽是可以的):
setClass("A",
slots = c(x="numeric", y = "character"),
prototype = list(
x = numeric(0),
y = character(0)
),
validity=function(object){
if(length(object@x) == 0){
warning("x slot is empty")
}
if(length(object@y) == 0){
warning("y slot is empty")
}
return(TRUE)
})
setMethod("initialize", signature = "A",
definition = function(.Object, x, y)
{
if (!missing(x)) {
.Object@x <- x
} else {
.Object@x <- numeric(0)
}
if (!missing(y)) {
.Object@y <- y
} else {
.Object@y <- character(0)
}
validObject(.Object)
return(.Object)
} )
new("A", x=1:10)
# warning message "validityMethod(object) : y slot is empty"
但是当如下创建 B 类对象时,即使传递了参数,我也会收到有效性消息,并且它们是重复的:
setClass("B",
slots = c(a = "data.frame"),
contains = "A",
validity = function(object) {
if (length(object@a) == 0) {
warning("a is empty")
}
return(TRUE)
})
setMethod("initialize", signature = "B",
definition = function(.Object, a, ...)
{
.Object@a <- a
.Object <- callNextMethod(.Object, ...)
validObject(.Object)
return(.Object)
} )
new("B", a = data.frame(10), x = 5, y = "c")
# gives warning messages:
#1: in validityMethod(object) : x slot is empty
#2: in validityMethod(object) : y slot is empty
#3: in validityMethod(object) : x slot is empty
#4: in validityMethod(object) : y slot is empty
当某个参数确实缺失时,我会收到附加消息(再次重复):
new("B", a = data.frame(10), x = 5)
# warning:
#
#1: in validityMethod(object) : x slot is empty
#2: in validityMethod(object) : y slot is empty
#3: in validityMethod(as(object, superClass)) : y slot is empty
#4: in validityMethod(object) : x slot is empty
#5: in validityMethod(object) : y slot is empty
#6: in validityMethod(as(object, superClass)) : y slot is empty
如何避免这些重复的消息并使它们起作用(仅当参数确实丢失时)?
一些事情:
TRUE
或字符串,而不是信号条件。 条件信号由 validObject
处理,而不是有效性方法本身。 在任何情况下,正式类的对象都是有效或无效的,因此在有效性方法中抛出警告(表明对象可以是准有效或准无效)确实是不寻常的。prototype=
。if (<missing>) <assign prototype> else <assign value>
方法中的 initialize
模式是拼凑的。 默认方法已经完成了所有这些工作,因此请分派给它。将所有内容放在一起:
setClass("A", slots = c(x = "numeric", y = "character"))
setMethod("initialize", "A",
function(.Object, ...) {
.Object <- callNextMethod()
if (length(.Object@x) == 0L)
warning("zero-length 'x' slot")
if (length(.Object@y) == 0L)
warning("zero-length 'y' slot")
.Object
})
setClass("B", contains = "A", slots = c(a = "data.frame"))
setMethod("initialize", "B",
function(.Object, ...) {
.Object <- callNextMethod()
if (length(.Object@a) == 0L)
warning("zero-length 'a' slot")
.Object
})
> new("A")
An object of class "A"
Slot "x":
numeric(0)
Slot "y":
character(0)
Warning messages:
1: In initialize(value, ...) : zero-length 'x' slot
2: In initialize(value, ...) : zero-length 'y' slot
> new("B")
An object of class "B"
Slot "a":
data frame with 0 columns and 0 rows
Slot "x":
numeric(0)
Slot "y":
character(0)
Warning messages:
1: In .nextMethod(.Object = .Object) : zero-length 'x' slot
2: In .nextMethod(.Object = .Object) : zero-length 'y' slot
3: In initialize(value, ...) : zero-length 'a' slot
> new("B", y = "")
An object of class "B"
Slot "a":
data frame with 0 columns and 0 rows
Slot "x":
numeric(0)
Slot "y":
[1] ""
Warning messages:
1: In .nextMethod(.Object = .Object, ... = ...) : zero-length 'x' slot
2: In initialize(value, ...) : zero-length 'a' slot