我想定义两个S4类,其中一个包含另一个。较低的类有一个特定的槽,比如x
,我需要object@x
的行为不同,这取决于object
是较低的类还是包装类。例如:
setClass("foo",
contains = "numeric",
slots = c(x = "character"))
setClass("bar",
contains = "foo")
ff <- new("foo", 1:10, x = "abc")
bb <- new("bar", ff)
现在,从这里我得到:
> ff@x
[1] "abc"
> bb@x
[1] "abc"
我想在调用bb@x
时,拦截"abc"
并修改它,使bb@x
产生与ff@x
不同的东西。
我尝试为bar
设置自定义@
方法:
setMethod("@", signature(x = "bar"),
function(x, slot) {
out <- x@slot
if (slot == "x") {
out <- toupper(out)
}
out
})
,但它失败了,出现以下错误:
> Error in setGeneric(f, where = where) :
must supply a function skeleton for ‘@’, explicitly or via an existing function
我尝试使用method.skeleton
,但这个错误也是:
> method.skeleton("@", "bar")
Error in genericForBasic(name) :
methods may not be defined for primitive function ‘@’ in this version of R
还有其他选择吗?
让@
根据不同的对象表现不同,在我看来,是一个非常糟糕的设计选择。
为什么不创建一个全新的函数,例如getx
,如下所示:
setGeneric("getx", function(object) object@x)
setMethod("getx", "bar", function(object) toupper(object@x))
setGeneric("getx<-", function(object, value) {
object@x <- value
object
})
# test drive
getx(ff) # abc
getx(bb) # ABC
getx(bb) <- "zxcm"
getx(bb) # ZXCM