2011-07-22 156 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調用中調用)並使用默認值。