2011-07-22 126 views
2

我有一个超类fb的类层次结构,其中没有对象应该存在(我试过虚拟类,但遇到了无法从虚拟类初始化对象的问题)。此外,我有两个子类(foo,bar)具有相同的插槽。现在我想建立一个新的对象,使用初始化方法返回基于某个值的一个子类的对象超:有没有办法初始化S4对象,以便返回另一个对象?

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" 
    [email protected] <- 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

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, ...) 
    [email protected] <- x 
    .Object 
}) 

行虽然经常(在这种情况下,如果initialize只是做时隙分配)没有必要的初始化方法在所有。请注意使用...,定位x(要求参数在相应的new调用中调用)并使用默认值。