2012-08-24 64 views
7

this相關的問題,但稍有不同,希望更清楚。使用正式方法定義爲S3對象分配S3風格

我正在尋找一個clean正式註冊S4和S3類的方法,但沒有依賴可怕的S3-dot-naming-scheme進行調度。舉個例子:

setClass("foo"); 
setClass("bar"); 

setGeneric("test", function(x, ...){ 
    standardGeneric("test"); 
}); 

setMethod("test", "bar", function(x, ...){ 
    return("success (bar)."); 
}); 

obj1 <- 123; 
class(obj1) <- "bar"; 
test(obj1); 

這個例子顯示我們如何註冊bar類的S3對象test方法,而不需要命名功能test.bar,這是偉大的。然而,限制是如果我們這樣註冊方法,它們將只被分派到對象的第一個S3類。 E.g:

obj2 <- 123; 
class(obj2) <- c("foo", "bar"); 
test(obj2); 

這是不行的,因爲S4方法調度將只嘗試foo類和其超。如何擴展此示例,以便在沒有找到foo的適當方法時,它會自動選擇test方法bar?例如。 S3風格派遣,但不必回頭去命名一切test.footest.bar

總之:如何創建一個使用形式方法調度的泛型函數,但是除此之外,您還需要回顧具有多個類的S3對象的第二,第三等對象類。

回答

2

你可以寫一個方法

test = function(x, ...) UseMethod("test") 

setGeneric("test") 

.redispatch = function(x, ...) 
{ 
    if (is.object(x) && !isS4(x) && length(class(x)) != 1L) { 
     class(x) = class(x)[-1] 
     callGeneric(x, ...) 
    } else callNextMethod(x, ...) 
} 

setMethod(test, "ANY", .redispatch) 

但我個人不會以這種方式混合S3和S4。

+0

是的,我一直在做類似的事情;然而事實上,你實際上改變x的class屬性可能會產生不良的副作用......有什麼辦法可以在不修改對象本身的情況下將它分派給下一個方法? – Jeroen

+0

我沒有你的答案;我認爲在S3類「酒吧」上工作的「酒吧」的S4方法是實施的一個偶然事件,而且你在非常不穩固的基礎上構建了一個複雜的結構。 –

3

?setOldClass將給出答案:

setOldClass(c("foo", "bar")) 

setGeneric("test", function(x, ...)standardGeneric("test")) 
setMethod("test", "bar", function(x, ...)return("success (bar).")) 
+0

所以這正是*不*我想要的。它需要類「foo」和「bar」之間的正式繼承,這可能並非如此。我希望它適用於任何具有class = [x,「bar」]的任意對象,對於x =任何內容,無需爲每個可能的類x聲明x和「bar」之間的繼承。假設有人用類[「zoo」,「bar」]創建了一個對象,那麼'test()'函數應該足夠聰明,以便爲「bar」選擇方法。 – Jeroen