有没有办法初始化S4对象,以便返回另一个对象?

时间:2011-07-22 12:48:56

标签: oop r initialization s4

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

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构造?

1 个答案:

答案 0 :(得分: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是一个构造函数,对用户来说更方便,并将接口与类层次结构与其实现分开,这通常被视为一件好事。

对于值得对S4 initialize方法进行隐式约束的是new("foo")(使用类名称调用new但没有其他参数)必须工作(否则会出现故障)你试图扩展foo)。所以初始化方法的范例是

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

虽然经常(在这种情况下,initialize正在进行插槽分配),根本不需要初始化方法。请注意...的使用,x的定位(要求在对new的相应调用中命名参数)以及使用默认值。