2

我有一个类层次结构,其超类fb不应该存在任何对象(我尝试了虚拟类,但遇到了无法从虚拟类初始化对象的问题)。此外,我有两个具有相同插槽的子类 ( foo, )。bar现在我想创建一个新对象,对超类使用初始化方法,该方法根据某个值返回子类之一的对象:

setClass("fb", representation( x = "numeric"))

setClass("foo", contains = "fb")
setClass("bar", contains = "fb")

setMethod("initialize", "fb", function(.Object, x) {
    if (x < 5) class(.Object) <- "foo"
    else class(.Object) <- "bar"
    .Object@x <- x
    .Object
})

> new("fb", x = 3)
Error in initialize(value, ...) : 
  initialize method returned an object of class "foo" instead of the required class "fb"

显然(并且可能有充分的理由)R 不允许这样做。有没有办法在方法中实现我想要的,而不是在创建新对象时使用 if-else 构造?

4

1 回答 1

4

S4 帮助我们在线条内着色。所以你的fb类应该是虚拟的,你的initialize方法不应该改变.Object. 您可能会编写一个fb执行条件实例化的函数。

setClass("fb", representation( x = "numeric", "VIRTUAL"))
setClass("foo", contains = "fb")
setClass("bar", contains = "fb")

fb <-
    function(x)
{
    if (x < 5) new("foo", x=x)
    else new("bar", x=x)
}

fb是一个构造函数,对用户来说更方便,并将类层次结构的接口与其实现分开,这通常被认为是一件好事。

initialize对于 S4方法的隐含约束是值得的new("foo")(使用类名调用new但没有附加参数)必须有效(否则尝试扩展 foo 时会失败)。所以初始化方法的范式是沿着

setMethod(initialize, "foo", function(.Object, ..., x=1) {
    .Object <- callNextMethod(.Object, ...)
    .Object@x <- x
    .Object
})

尽管通常(在这种情况下, whereinitialize只是进行插槽分配)根本不需要初始化方法。注意 的使用...、的定位x(要求在相应的调用中命名参数new)和默认值的使用。

于 2011-07-22T14:51:56.973 回答